C#排序算法——二路归并法

  在阅读此博文前,请先阅读我的博文“C#排序算法——基类设计 “,以了解基类的结构。
  在编写代码前,我们先来了解二路归并法的排序过程:
  假设有一个IList<T>型的集合list(集合的元素为list[0]到list[n-1], n = list.Count)。
  第1步:将list平均分为两个子集:左子集list[0]:list[middle]和右子集list[middle + 1]:list[n - 1](middle = n / 2)。
  第2步:分别对左子集和右子集用二路归并法进行排序。
  第3步,将排序后的左子集和右子集合并,构造出有序集合list.
  很显然,二路归并法使用了递归调用。根据上面的算法,我们开始编码了:

  1. using  System;
  2. using  System.Collections.Generic;
  3. using  System.Text;
  4. namespace  CYB.DataStruct.Sorting
  5. {
  6.      /// <summary>
  7.      /// 作者 : cyb
  8.      /// 发表时间 : 2008-9-8
  9.      /// qq : 13101908
  10.      /// e-mail : hustcyb@gmail.com
  11.      /// </summary>
  12.      public   class  MergeSorter : Sorter
  13.     {
  14.          public   override   void  Sort<T>(IList<T> list, CompareDelegate<T> compare)
  15.         {
  16.              base .Sort(list, compare);
  17.              this .Sort(list, 0, list.Count - 1, compare);
  18.         }
  19.          private   void  Merge<T>(IList<T> list,  int  start,  int  middle,  int  end, CompareDelegate<T> compare)
  20.         {
  21.             T[] array =  new  T[end - start + 1];   //存储集合元素的临时数组
  22.              int  index = 0;       //指示arry中位置的游标
  23.              int  left = start;    //指示左子集位置的游标  
  24.              int  right = middle + 1;      //指示右子集位置的游标
  25.              while  (left <= middle && right <= end)
  26.             {
  27.                  if  (compare(list[left], list[right]) < 0)
  28.                 {
  29.                     array[index++] = list[left++];
  30.                 }
  31.                  else
  32.                 {
  33.                     array[index++] = list[right++];
  34.                 }
  35.             }
  36.              //将左子集中剩余元素复制到临时数组中(如果还有的话)
  37.              while  (left <= middle)
  38.             {
  39.                 array[index++] = list[left++];
  40.             }
  41.              //将右子集中剩余元素复制到临时数组中(如果还有的话)
  42.              while  (right <= end)
  43.             {
  44.                 array[index++] = list[right++];
  45.             }
  46.              //将有序的临时数组复制到集合中
  47.              for  (index = 0; index < array.Length; index++)
  48.             {
  49.                 list[start + index] = array[index];
  50.             }
  51.         }
  52.          private   void  Sort<T>(IList<T> list,  int  start,  int  end, CompareDelegate<T> compare)
  53.         {
  54.              if  (start >= end)
  55.             {
  56.                  return ;      //当集合中的元素少于1个,不作处理
  57.             }
  58.              //分割集合
  59.              int  middle = (start + end) / 2;
  60.             Sort(list, start, middle, compare);      //使用二路归并法对左子集排序
  61.             Sort(list, middle + 1, end, compare);    //使用二路归并法对右子集排序
  62.             
  63.              //合并子集
  64.             Merge(list, start, middle, end, compare);
  65.         }
  66.     }
  67. }
  另一种二路归并排序算法是这样的:首先将每两个相邻的大小为1的子序列归并,然后对
上一次归并所得到的大小为2的子序列进行相邻归并,如此反复,直至最后归并到一个序列,
归并过程完成:

  1. using  System;
  2. using  System.Collections.Generic;
  3. using  System.Text;
  4. namespace  CYB.DataStruct.Sorting
  5. {
  6.      /// <summary>
  7.      /// 作者 : cyb
  8.      /// 发表时间 : 2008-9-8
  9.      /// qq : 13101908
  10.      /// e-mail : hustcyb@gmail.com
  11.      /// </summary>
  12.      public   class  MergeSorter : Sorter
  13.     {
  14.          public   override   void  Sort<T>(IList<T> list, CompareDelegate<T> compare)
  15.         {
  16.              base .Sort(list, compare);
  17.             Sort(list, 1, compare);
  18.         }
  19.          private   void  Sort<T>(IList<T> list,  int  interval, CompareDelegate<T> compare)
  20.         {
  21.              if  (interval >= list.Count)
  22.             {
  23.                  return ;
  24.             }
  25.              for  ( int  middle = interval - 1; middle < list.Count; middle += 2 * interval)
  26.             {
  27.                  int  start = middle - (interval - 1);
  28.                  int  end = middle + interval;
  29.                  if  (end >= list.Count)
  30.                 {
  31.                     end = list.Count - 1;
  32.                 }
  33.                 Merge(list, start, middle, end, compare);
  34.             }
  35.             Sort(list, 2 * interval, compare);
  36.         }
  37.          private   void  Merge<T>(IList<T> list,  int  start,  int  middle,  int  end, CompareDelegate<T> compare)
  38.         {
  39.             T[] array =  new  T[end - start + 1];   //存储集合元素的临时数组
  40.              int  index = 0;       //指示arry中位置的游标
  41.              int  left = start;    //指示左子集位置的游标  
  42.              int  right = middle + 1;      //指示右子集位置的游标
  43.              while  (left <= middle && right <= end)
  44.             {
  45.                  if  (compare(list[left], list[right]) < 0)
  46.                 {
  47.                     array[index++] = list[left++];
  48.                 }
  49.                  else
  50.                 {
  51.                     array[index++] = list[right++];
  52.                 }
  53.             }
  54.              //将左子集中剩余元素复制到临时数组中(如果还有的话)
  55.              while  (left <= middle)
  56.             {
  57.                 array[index++] = list[left++];
  58.             }
  59.              //将右子集中剩余元素复制到临时数组中(如果还有的话)
  60.              while  (right <= end)
  61.             {
  62.                 array[index++] = list[right++];
  63.             }
  64.              //将有序的临时数组复制到集合中
  65.              for  (index = 0; index < array.Length; index++)
  66.             {
  67.                 list[start + index] = array[index];
  68.             }
  69.         }
  70.     }
  71. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值