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

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),不是稳定的排序算法。

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),是不稳定的排序算法。

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),是稳定的排序方法。

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),不是稳定的排序算法。

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),是稳定的排序算法。

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 }