C#排序算法——基类的实现

 

  论坛中经常有人问选择法、冒泡法排序算法用C# 怎么实现,正好我手头上有这方面的代码,干脆拿出来跟大家分享一下。其实代码已经写了很久了,只是平时工作比较忙,没时间整理。现在失业了,每天呆在家里实在无聊,就抽空把这部分代码整理出来。好了,废话少说,进入正题吧。
  排序算法,首先应该考虑的是通用性,不管是数组,还是List<T> 都应该支持,那肯定要用到泛型了,那么是不是应该用形如下面的实现呢?

  1.      public   class  Sorter
  2.     {
  3.          public   void  Sort<T>(T[] array)
  4.         {
  5.              //数组的排序算法
  6.         }
  7.          public   void  Sort<T>(List<T> list)
  8.         {
  9.              //List<T>的排序算法
  10.         }
  11.     }

  这是C++ 的风格,不是C# 的风格。那么C# 的风格是什么?当然是接口了。那么数组和List<T> 有共同的接口吗?当然有了,那就是IList<T> 接口。好了,类型的形式已经确定了。
  好了,那下一步泛型应该采用什么形式呢?
  形式(1):

  1.      public   class  Sorter<T>
  2.     {
  3.          public   void  Sort(IList<T> sort)
  4.         {
  5.              //排序过程
  6.         }
  7.     }

  形式(2):

  1.      public   class  Sorter
  2.     {
  3.          public   void  Sort<T>(IList<T> sort)
  4.         {
  5.              //排序过程
  6.         }
  7.     }

   咋一看,当然是选择形式(1 )了,尤其是当Sorter 类有多个Sort 方法时候。其实不然,因为Sorter 类只有函数成员,没有数据成员,要排序的数据作为参数传递结Sort 方法。那你可能会问,编码的时候要在每一个Sort 方法名称后加上<T>, 不是很麻烦吗?不错,采用形式(2 )编码的时候的确麻烦,但是我们的排序算法是要做成类库的,是要供大家反复调用的。那么你在调用的时候是愿意使用下面那种形式呢?
  形式(1)的调用:

    •      int [] array = { 3, 7, 2, 1 };
    •     Sorter< int >.Sort(array);

  形式(2)的调用:

  1.      int [] array = { 3, 7, 2, 1 };
  2.     Sorter.Sort(array);      //注意这里可以不用加数据类型,运行的时候会自动识别参数的类型

  毫无疑问,你肯定会选择形式(2)了。好了,泛型的形式也确定了。
  下一步该考虑Sorter 类的设计了,是应该把Sorter 设计成工具类吗?

    •      public   class  Sorter
    •     {
    •          public   static   void  BubbleSort<T>(IList<T> list)
    •         {
    •              //冒泡法排序
    •         }
    •          public   static   void  SelectionSort<T>(IList<T> list)
    •         {
    •              //选择排序
    •         }
    •          //
    •          //其他排序算法
    •          //
    •     }

  这也太不符合面向对象的概念了,面向对象的精髓是什么?继承、封装与多态。没错,这里我们继承和多态,将Sorter 设计成虚拟基类,而具体的排序过程留到子类中实现。整个类库的形式应该如下:

  1.      /// <summary>
  2.      /// 虚拟基类
  3.      /// </summary>
  4.      public   abstract   class  Sorter
  5.     {
  6.          public   abstract   void  Sort<T>(IList<T> list);
  7.     }
  8.      /// <summary>
  9.      /// 冒泡法
  10.      /// </summary>
  11.      public class  BubbleSorter : Sorter
  12.     {
  13.          public   override   void  Sort<T>(IList<T> list)
  14.         {
  15.              //排序过程
  16.         }
  17.     }
  18.      /// <summary>
  19.      /// 选择法
  20.      /// </summary>
  21.      public class  SelectionSort : Sorter
  22.     {
  23.          public   override   void  Sort<T>(IList<T> list)
  24.         {
  25.              //排序过程
  26.         }
  27.     }
  28.      //
  29.      //其他排序方法
  30.      // 

  好了,既然是排序,当然要涉及到比较的问题了,C#中提供两种比较的方法:IComparable<T>和IComparer<T>接口,IComparable接口有唯一的一个方法:

  1.       int  CompareTo(T other);    

  IComparer<T> 接口也只有一个方法:

  1.      int  Compare(T x, T y);

  两者参数的个数不一样,怎么把他们统一起来?当然是用委托啦。先定义一个委托:

  1.       public   delegate   int  CompareDelegate<T>(T left, T right);

 

  然后稍微改变一下Sorter 类的代码:

  1.      /// <summary>
  2.      /// 虚拟基类
  3.      /// </summary>
  4.      public   abstract   class  Sorter
  5.     {
  6.          public   abstract   void  Sort<T>(IList<T> list, CompareDelegate<T> compare);  //抽象排序算法,由子类实现
  7.          public   void  Sort<T>(IList<T> list) where T : IComparable<T>
  8.         {
  9.             CompareDelegate<T> compare =  delegate (T left, T right)
  10.             {
  11.                  return  left.CompareTo(right);
  12.             };
  13.             Sort(list, compare);
  14.         }
  15.          public   void  Sort<T>(IList<T> list, IComparer<T> comparer)
  16.         {
  17.             Sort(list, comparer.Compare);
  18.         }
  19.     }

  最后,关于升序排列和降序排列的问题。你可能会认为,这还不简单,只要稍微改变IComparable<T>类型的ComparetTo方法就可以了。那么对于int、double这样的内置数据类型或者第三方提供的类型,你无法改变其源代码,那怎么处理?当然办法还是有的,自定义一个IComparer<T>类。那要对同一类型,要求既可以进行升序排列又可以进行降序排列怎么办?当然办法还是有的,定义两个IComparer<T>类,分别用于升序和降序排列。但是这些办法都不够灵活。这里,我们的Sorter基类将升序排列和降序排列考虑进来,得到了Sorter类的最终版本:

  1. using  System;
  2. using  System.Collections.Generic;
  3. using  System.Text;

  4. namespace  CYB.DataStruct.Sorting
  5. {
  6.      /// <summary>
  7.      /// 用于定义升序和降序的枚举
  8.      /// </summary>
  9.      public   enum  Order
  10.     {
  11.         ASC,
  12.         DESC,
  13.     }

  14.      public   delegate   int  CompareDelegate<T>(T left, T right);

  15.      /// <summary>
  16.      /// 作者 : cyb
  17.      /// 发表时间 : 2008-9-8
  18.      /// qq : 13101908
  19.      /// e-mail : hustcyb@gmail.com
  20.      /// </summary>
  21.      public   abstract   class  Sorter
  22.     {
  23.          public   virtual   void  Sort<T>(IList<T> list, CompareDelegate<T> compare)
  24.         {
  25.              if  (list ==  null )
  26.             {
  27.                  throw   new  ArgumentNullException( "Argument for IList is null" );
  28.             }

  29.              if  (compare ==  null )
  30.             {
  31.                  throw   new  ArgumentNullException( "Argument for CompareDelegate is null" );
  32.             }
  33.         }

  34.          public   void  Sort<T>(IList<T> list, Order order) where T : IComparable<T>
  35.         {
  36.             CompareDelegate<T> compare;

  37.              if  (order == Order.ASC)
  38.             {
  39.                 compare =  delegate (T first, T second)
  40.                 {
  41.                      return  first.CompareTo(second);
  42.                 };
  43.             }
  44.              else
  45.             {
  46.                 compare =  delegate (T first, T second)
  47.                 {
  48.                      return  -first.CompareTo(second);
  49.                 };
  50.             }

  51.             Sort(list, compare);
  52.         }

  53.          public   void  Sort<T>(IList<T> list) where T : IComparable<T>
  54.         {
  55.              this .Sort(list, Order.ASC);
  56.         }

  57.          public   void  Sort<T>(IList<T> list, IComparer<T> comparer, Order order)
  58.         {
  59.             CompareDelegate<T> compare;

  60.              if  (order == Order.ASC)
  61.             {
  62.                 compare =  delegate (T first, T second)
  63.                 {
  64.                      return  comparer.Compare(first, second);
  65.                 };
  66.             }
  67.              else
  68.             {
  69.                 compare =  delegate (T first, T second)
  70.                 {
  71.                      return  -comparer.Compare(first, second);
  72.                 };
  73.             }

  74.             Sort(list, compare);
  75.         }

  76.          public   void  Sort<T>(IList<T> list, IComparer<T> comparer)
  77.         {
  78.              this .Sort(list, comparer, Order.ASC);
  79.         }

  80.          /// <summary>
  81.          /// 交换集合中的两个元素,子类中会用到
  82.          /// </summary>
  83.          public   static   void  SwapListItem<T>(IList<T> list,  int  firstIndex,  int  secondIndex)
  84.         {
  85.             T temp = list[firstIndex];
  86.             list[firstIndex] = list[secondIndex];
  87.             list[secondIndex] = temp;
  88.         }
  89.     }
  90. }

  这里要注意一点,IComparable<T>和IComparer<T>的CompareTo方法是假定为升序排列编写的,否则Order.ASC和Order.DESC就没有意义了。
  磨刀不误砍柴功,基类设计好了,子类的实现就比较简单了。子类的实现即排序的具体细节将会在近期整理出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值