C#实现常用排序算法

  本文实现的常用排序算法包括:冒泡排序,快速排序,希尔排序,插入排序,选择排序,归并排序。

  冒泡排序:从后向前遍历数组,比较相邻的两个元素。如果两个元素的顺序是错的,那么就交换这两个元素。如果某次遍历过程中,元素都没有发生交换,那么说明数组已经排序好,可以中止停止排序。最坏的情况是在起始数组中,需要排在最后的元素位于最前边,那么冒泡算法必须经过n-1次遍历才能将数组排列好,而不能提前完成排序。该算法的时间复杂度是O(n^2),是稳定的排序算法。

BubbleSort
 1         /// <summary>
 2         /// 冒泡排序
 3         /// </summary>
 4         /// <param name="array">待排序的数组</param>
 5         /// <param name="isReverse">是否逆序</param>
 6         /// <param name="sortedArray">排序后的数组</param>
 7         public static void BubbleSort(IEnumerable<T> array, bool isReverse, out List<T> sortedArray)
 8         {
 9             sortedArray = array.ToList();
10             int n = sortedArray.Count; ;
11             int sign;//结束标记
12             for (int j = 0; j < n - 1; j++)
13             {
14                 sign = 0;
15                 for (int i = n - 1; i > j; i--)
16                 {
17                     T item = sortedArray[i];
18                     T preItem = sortedArray[i - 1];
19                     if (isReverse && item.CompareTo(preItem) > 0 || //逆序
20                         !isReverse && item.CompareTo(preItem) < 0)  //顺序
21                     {
22                         sign = 1;//不能结束
23                         Swap(sortedArray, i, i-1);//交换元素的位置
24                     }
25                 }
26                 if (sign < 1)
27                     break;
28             }
29         }

  快速排序:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。该算法是对冒泡排序的改进算法,时间复杂度是O(n*logn),不是稳定的排序算法。

QuickSort
 1         /// <summary>
 2         /// 快速排序
 3         /// </summary>
 4         /// <param name="array">待排序的数组</param>
 5         /// <param name="isReverse">是否逆序</param>
 6         /// <param name="sortedArray">排序后的数组</param>
 7         public static void QuickSort(IEnumerable<T> array, bool isReverse, out List<T> sortedArray)
 8         {
 9             sortedArray = array.ToList();
10             int n = sortedArray.Count;
11 
12             int key = 0;//选取第一个元素为两部分数据的分割项的索引
13 
14             //将数组分割成两部分
15             int i = 0, j = n - 1;
16             while(i < j)
17             {
18                 while (j > i)
19                 {
20                     if (isReverse && sortedArray[j].CompareTo(sortedArray[key]) > 0 ||
21                         !isReverse && sortedArray[j].CompareTo(sortedArray[key]) < 0)
22                     {
23                         Swap(sortedArray, j, i);
24                         key = j;
25                         break;
26                     }
27                     j--;
28                 }
29                 while (i < j)
30                 {
31                     if (isReverse && sortedArray[i].CompareTo(sortedArray[key]) < 0 ||
32                         !isReverse && sortedArray[i].CompareTo(sortedArray[key]) > 0)
33                     {
34                         Swap(sortedArray, j, i);
35                         key = i;                        
36                         break;
37                     }
38                     i++;
39                 }
40             }   
41             if (n <= 2) return;//结束条件
42             else
43             {
44                 //递归调用,对key前面的数组进行排序
45                 List<T> array1 = new List<T>();
46                 for (i = 0; i < key; i++)
47                 {
48                     array1.Add(sortedArray[i]);
49                 }
50                 QuickSort(array1, isReverse, out array1);
51                 for (i = 0; i < key; i++)
52                 {
53                     sortedArray[i] = array1[i];
54                 }
55                 //递归调用,对key后面的数组进行排序
56                 List<T> array2 = new List<T>();
57                 for (i = 0; i < n - key - 1; i++)
58                 {
59                     array2.Add(sortedArray[key + 1 + i]);
60                 }
61                 QuickSort(array2, isReverse, out array2);
62                 for (i = 0; i < array2.Count; i++)
63                 {
64                     sortedArray[key + 1 + i] = array2[i];
65                 }
66             }
67         }

  希尔排序:将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d。对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。该算法是对冒泡排序的改进,又称缩小增量排序,也可配合其他排序算法使用。该算法的时间复杂度是O(n*logn),是不稳定的排序算法。

ShellSort
 1         /// <summary>
 2         /// 希尔排序
 3         /// </summary>
 4         /// <param name="array">待排序的数组</param>
 5         /// <param name="isReverse">是否逆序</param>
 6         /// <param name="sortedArray">排序后的数组</param>
 7         public static void ShellSort(IEnumerable<T> array, bool isReverse, out List<T> sortedArray)
 8         {
 9             sortedArray = array.ToList();
10             int n = sortedArray.Count;
11             //初始化增量
12             int step = 1;
13             while (step < n) step = 3 * step + 1;
14 
15             while (step > 1)
16             {
17                 step = step / 3 + 1;
18                 for (int i = 0; i < step; i++)
19                 {
20                     int nsub = (n - i - 1) / step + 1;
21                     List<T> subArray = new List<T>();
22                     for (int j = 0; j < nsub; j++)
23                     {
24                         subArray.Add(sortedArray[i + j * step]);
25                     }
26                     BubbleSort(subArray, isReverse, out subArray);//此处也可使用其他排序算法
27                     for (int j = 0; j < nsub; j++)
28                     {
29                         sortedArray[i + j * step] = subArray[j];
30                     }
31                 }
32             }
33         }

  插入排序:假定这个数组的序是排好的,然后从头往后,如果有数比当前外层元素的值大,则将这个数的位置往后挪,直到当前外层元素的值大于或等于它前面的位置为止。算法适用于少量数据的排序,时间复杂度为O(n^2),是稳定的排序方法。

InsertSort
 1         /// <summary>
 2         /// 插入排序
 3         /// </summary>
 4         /// <param name="array">待排序的数组</param>
 5         /// <param name="isReverse">是否逆序</param>
 6         /// <param name="sortedArray">排序后的数组</param>
 7         public static void InsertSort(IEnumerable<T> array, bool isReverse, out List<T> sortedArray)
 8         {
 9             sortedArray = array.ToList();
10             int n = sortedArray.Count;
11             for (int j = 1; j < n; j++)
12             {
13                 int i = j - 1;
14                 T item = sortedArray[i];
15                 T nextItem = sortedArray[i + 1];
16                 while (isReverse && item.CompareTo(nextItem) < 0 ||
17                       !isReverse && item.CompareTo(nextItem) > 0)
18                 {
19                     Swap(sortedArray, i, i + 1);//交换元素的位置
20                     i--;
21                     if (i >= 0)
22                     {
23                         item = sortedArray[i];
24                         nextItem = sortedArray[i + 1];
25                     }
26                     else
27                     {
28                         break;
29                     }
30                 }               
31             }
32         }

  选择排序:先找到起始数组中最小的元素,将它交换到i=0;然后寻找剩下元素中最小的元素,将它交换到i=1的位置…… 直到找到第二大的元素,将它交换到n-2的位置。这时,整个数组的排序完成。该算法的时间复杂度是O(n^2),不是稳定的排序算法。  

SelectSort
 1         /// <summary>
 2         /// 选择排序
 3         /// </summary>
 4         /// <param name="array">待排序的数组</param>
 5         /// <param name="isReverse">是否逆序</param>
 6         /// <param name="sortedArray">排序后的数组</param>
 7         public static void SelectSort(IEnumerable<T> array, bool isReverse, out List<T> sortedArray)
 8         {
 9             sortedArray = array.ToList();
10             int n = sortedArray.Count;
11             int selectIndex;
12             for (int j = 0; j < n - 1; j++)
13             {
14                 selectIndex = j;
15                 for (int i = j + 1; i < n; i++)
16                 { 
17                     T item = sortedArray[i];
18                     if ((isReverse && sortedArray[selectIndex].CompareTo(item) < 0) ||
19                         (!isReverse && sortedArray[selectIndex].CompareTo(item) > 0))
20                     {
21                         selectIndex = i;
22                     }
23                 }
24                 Swap(sortedArray, selectIndex, j);
25             }
26         }

  归并排序:将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。该算法的时间复杂度是O(n*logn),是稳定的排序算法。 

MergeSort
 1         /// <summary>
 2         /// 归并排序
 3         /// </summary>
 4         /// <param name="array">待排序的数组</param>
 5         /// <param name="isReverse">是否逆序</param>
 6         /// <param name="sortedArray">排序后的数组</param>
 7         public static void MergeSort(IEnumerable<T> array, bool isReverse, out List<T> sortedArray)
 8         {
 9             sortedArray = array.ToList();
10             int n = sortedArray.Count;
11 
12             if (n <= 1) return;//结束标识
13             
14             //将数组分为两个数组
15             int n1 = n / 2;
16             List<T> array1 = new List<T>();
17             for (int k = 0; k < n1; k++)
18             {
19                 array1.Add(sortedArray[k]);
20             }
21             int n2 = n - n1;
22             List<T> array2 = new List<T>();
23             for (int k = 0; k < n2; k++)
24             {
25                 array2.Add(sortedArray[n1 + k]);
26             }
27 
28             //递归调用
29             MergeSort(array1, isReverse, out array1);
30             MergeSort(array2, isReverse, out array2);
31 
32             //合并有序序列
33             int i = 0, j = 0;//array1和array2的索引
34             int index = 0;//sortedArray的索引
35             while (i < n1 && j < n2)
36             {                
37                 if (isReverse && array1[i].CompareTo(array2[j]) > 0 ||
38                     !isReverse && array1[i].CompareTo(array2[j]) <= 0)
39                 {
40                     sortedArray[index++] = array1[i++];
41                 }
42                 else
43                 {
44                     sortedArray[index++] = array2[j++];
45                 }                
46             }
47             while (i < n1)
48             {
49                 sortedArray[index++] = array1[i++];
50             }
51             while (j < n2)
52             {
53                 sortedArray[index++] = array2[j++];
54             }
55         }
原文地址:https://www.cnblogs.com/hibernation/p/2961036.html