zoukankan      html  css  js  c++  java
  • 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         }
  • 相关阅读:
    基于Tags实现内容推荐的方法(代码)
    洞察未来
    技术人员工作原则
    罗辑思维CEO脱不花:关于工作和成长,这是我的121条具体建议
    王兴:8年时间,我对商业的思考
    100个管理定律
    李想:关于工作和成长,这是我的100条具体建议 |【经纬低调分享】
    C++--win32
    谈谈javaSE中的==和equals的联系与区别
    Vue 基础知识
  • 原文地址:https://www.cnblogs.com/hibernation/p/2961036.html
Copyright © 2011-2022 走看看