快速排序算法的C#实现

原文链接:http://www.cnblogs.com/heyuquan/p/bubble-quick-sort.html

完整可运行的控制台应用程序源码:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 
  6 namespace algorithm
  7 {
  8     class Program
  9     {
 10         public enum QuickType { Normal = 1, Random, Balance };
 11 
 12         private static Random random = null;
 13 
 14          /// <summary>
 15          /// 程序入口
 16          /// </summary>
 17          /// <param name="args"></param>
 18         private static void Main(string[] args)
 19         {
 20             Console.Title = "快速排序测试";
 21 
 22             int size = 30000000;//随机数组大小,可修改
 23             int max = 10000000;//随机数的上界,可修改
 24             int[] array = new int[size];
 25 
 26             //产生随机数组
 27             Random rdm = new Random();
 28             for (int i = 0; i < size; i++)
 29             {
 30                 array[i] = rdm.Next(1, max);
 31             }
 32 
 33             //输出随机数组
 34             for (int j = 0; j < size; j++)
 35             {
 36                 Console.Write(array[j] + "\t");
 37                 if ((j + 1) % 10 == 0)
 38                 {
 39                     Console.WriteLine();
 40                 }
 41             }
 42 
 43             Console.ReadLine();
 44             //对数组做排序处理
 45             Sort(array, QuickType.Normal); //采用快速排序,可修改
 46 
 47             //输出排序后的随机数组
 48             for (int j = 0; j < size; j++)
 49             {
 50                 Console.Write(array[j] + "\t");
 51                 if ((j + 1) % 10 == 0)
 52                 {
 53                     Console.WriteLine();
 54                 }
 55             }
 56             Console.ReadLine();
 57         }
 58 
 59         /// <summary>
 60         /// 优化的快速排序
 61         /// </summary>
 62         /// <param name="arr">待排序数组</param>
 63         /// <param name="quickType">排序算法</param>
 64         public static void Sort<T>(IList<T> arr, QuickType quickType = QuickType.Normal) where T : IComparable<T>
 65         {
 66             if (arr == null)
 67             {
 68                 throw new ArgumentNullException("arr");
 69             }
 70             switch (quickType)
 71             {
 72                 case QuickType.Normal:  // 快速排序
 73                     {
 74                         DoSort<T>(arr, 0, arr.Count() - 1,
 75                             (subArr, left, right) =>
 76                             {
 77                                 // 默认以第1个数为基数。
 78                                 // 所以,什么都不用做
 79                             }
 80                             );
 81                     }
 82                     break;
 83                 case QuickType.Random:  // 随机快排
 84                     {
 85                         DoSort<T>(arr, 0, arr.Count() - 1,
 86                             (subArr, left, right) =>
 87                             {
 88                                 if (subArr.Count > 10)
 89                                 {
 90                                     // 随机化快排:随机数组中一个元素做基准
 91                                     if (random == null)
 92                                         random = new Random(new Guid().GetHashCode());
 93                                     int index = random.Next(left, right);
 94 
 95                                     T temp = subArr[left];
 96                                     subArr[left] = subArr[index];
 97                                     subArr[index] = temp;
 98                                 }
 99                             }
100                             );
101                     }
102                     break;
103                 case QuickType.Balance: // 平衡快排
104                     {
105                         DoSort<T>(arr, 0, arr.Count() - 1,
106                             (subArr, left, right) =>
107                             {
108                                 if (subArr.Count > 10)
109                                 {
110                                     int index = -1;
111                                     // 平衡快排:取开头、结尾、中间3个数据,通过比较选出其中的中值
112                                     int middle = (left + right) / 2;
113 
114                                     // 取较小的数
115                                     if (subArr[middle].CompareTo(subArr[left]) >= 0)
116                                     {
117                                         index = left;
118                                     }
119                                     else
120                                     {
121                                         index = middle;
122                                     }
123 
124                                     // 再用较小的数去比较
125                                     if (subArr[index].CompareTo(subArr[right]) >= 0)
126                                     {
127                                         // 那么index就是中间元素
128                                     }
129                                     else
130                                     {
131                                         // index为最小元素,中间元素在left和right中
132                                         if (subArr[right].CompareTo(subArr[left]) >= 0)
133                                         {
134                                             index = left;
135                                         }
136                                         else
137                                         {
138                                             index = right;
139                                         }
140                                     }
141 
142                                     // 交换
143                                     T temp = subArr[left];
144                                     subArr[left] = subArr[index];
145                                     subArr[index] = temp;
146                                 }
147                             }
148                             );
149                     }
150                     break;
151             }
152         }
153 
154         /// <summary>
155         /// 快速排序
156         /// </summary>
157         /// <param name="arr">待排序数组</param>
158         /// <param name="left">左边界索引</param>
159         /// <param name="right">右边界索引</param>
160         /// <param name="SelectPivot">选择基准元素委托,并且将基元素与左边界元素交换</param>
161         private static void DoSort<T>(IList<T> arr, int left, int right
162             , Action<IList<T>, int, int> SelectPivot) where T : IComparable<T>
163         {
164             if (left < right)
165             {
166                 // 选择基准元素委托
167                 if (SelectPivot != null)
168                     SelectPivot(arr, left, right);
169 
170                 // 临时存储基准元素,以让其他数组元素来填充该位置
171                 T pivot = arr[left];
172                 int low = left;
173                 int high = right;
174 
175                 while (low < high)
176                 {
177                     // 从右向左找第一个小于 基数 的数  
178                     while (low < high && arr[high].CompareTo(pivot) >= 0)
179                         high--;
180                     if (low < high)
181                         arr[low++] = arr[high];
182 
183                     // 从左向右找第一个大于等于 基数 的数
184                     while (low < high && arr[low].CompareTo(pivot) < 0)
185                         low++;
186                     if (low < high)
187                         arr[high--] = arr[low];
188                 }
189                 arr[low] = pivot;   // 此时 low = high
190 
191                 // 两个分区递归。基准元素无需在参与下一次快速排序
192                 DoSort<T>(arr, left, low - 1, SelectPivot);
193                 DoSort<T>(arr, low + 1, right, SelectPivot);
194             }
195         }
196     }
197 }
posted @ 2014-11-15 12:52  天琊蓝  阅读(169)  评论(0编辑  收藏  举报