八大排序算法小结

来源:互联网 发布:米表源码 编辑:程序博客网 时间:2024/04/26 07:59

前言
        规定以下方法:
  • less(int i, int j):less方法用于对元素进行比较。如果i<j,返回true;否则返回false。
  • exch(int[] a, int i, int j):exch方法用于将元素交换位置。
  • show(int[] a):show方法用于展示排序结果。
        稳定性概念:
  • 稳定排序通俗地讲就是能保证排序前2个相等的数在其排序后相对次序不变,即如果Ai = Aj,Ai原来在位置前,排序后Ai还是要在Aj位置前,否则排序就是不稳定的。

选择排序
        
  • 原理:选择排序的工作原理是每一次从待排序的数据元素中选出最小的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
  • 步骤:
    1. 首先,在一趟排序中,找到数组中最小的那个元素。并将它与第一个元素交换位置。(如果第一个元素是最小元素那么它就和自己交换)
    2. 在下一趟排序中,找到剩下元素中最小的元素,将它与数组第二个元素交换位置。
    3. 如此往复,直到将整个数组排序。
  • 特点:
    • 运行时间和输入无关:一个已经有序的数组或是主键全部相等的数组和一个元素随机排列的数组所用的排序时间一样长。
    • 数据移动是最少的:每次交换都会改变两个数组元素的值,因此选择排序用了N次交换,交换次数和数组的大小是线性关系。
  • 适用场景:n较小,且不在意相同数据在排序后的相对次序,可以考虑选择排序。
  • 复杂度:对于长度为N的数组,选择排序需要大约N^2/2次比较和N次交换。故平均时间复杂度为O(n^2),空间复杂度为O(1)。
  • 稳定性:选择排序不是稳定排序,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么 交换后稳定性就被破坏了。
    • 例如:序列5 8 5 2 9, 经过第一遍选择后,第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。

插入排序
        
  • 原理:插入排序的原理是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。总之,插入排序需要每插入一个数,就对现有的数组进行重排序。
  • 步骤:
    1. 从第一个元素开始,该元素可以认为已经被排序
    2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
    3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
    4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
    5. 将新元素插入到下一位置中
    6. 重复步骤2~5,直至结束
  • 适用场景:插入排序对于部分有序的数组十分高效,也很适合小规模数组。
  • 复杂度:对于长度为N且主键不重复的数组,平均情况下插入排序需要~N^2/4次比较以及~N^2/4次交换。最坏情况下需要~N^2/2次比较和~N^2/2次交换,最好情况下需要N - 1次比较和0次交换。故平均时间复杂度为O(n^2),空间复杂度为O(1)。
  • 稳定性:插入排序是稳定排序。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。
    • 例如:序列12345已经排序,现要向其中插入5,因为其与序列中的最后一位5相同,故直接尾随其后,两个5之间的相对次序并没有改变。

冒泡排序
        
  • 原理:就像冒泡一样,越大的元素会经由两两交换慢慢“浮”到数列的顶端。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
  • 步骤:
    1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
    2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
    3. 针对所有的元素重复以上的步骤,除了最后一个。
    4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
  • 适用场景:n较小且要求相同数据在排序后的相对次序,可以考虑使用冒泡排序。
  • 复杂度:平均时间复杂度为O(n^2),空间复杂度为O(1)。
  • 稳定性:冒泡排序是稳定排序,若两个相等的元素没有相邻,在两两交换的过程中它们会相遇,但是不会交换彼此相对位置。

快速排序
        
  • 原理:通过一趟排序将要排序的数据分割成独立的两部分和一个KEY值,其中一部分的所有数据都比KEY小,另外一部分的所有数据都比KEY大,且这两部分都未排序,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
  • 步骤:
    1. 设置两个变量i、j,排序开始的时候:i=0,j=N-1。
    2. 以第一个数组元素作为关键数据,赋值给key,即key=A[0]。
    3. 从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j]。
    4. 从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i]。
    5. 将A[j]和A[i]互换。
    6. 重复第3、4、5步,直到i=j。 (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
  • 适用场景:广泛应用于不考虑稳定性的排序领域。
  • 复杂度:平均时间复杂度O(nlogn),空间复杂度O(logn)~O(n)。
  • 稳定性:快速排序不是稳定排序。因为在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱。
    • 例如:序列为5 3 3 4 3 8 9 10 11,现在j指向3,中枢元素为5,现在中枢元素5和3交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j] 交换的时刻。

归并排序
        
  • 原理:要将一个数组排序,可以先将它们分成两半分别排序,然后将结果归并起来。归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有序的长序列,不断合并直到原序列全部排好序。
  • 步骤:
    1. 第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列。
    2. 第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置。
    3. 第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置。
    4. 重复步骤3直到某一指针超出序列尾。
    5. 将另一序列剩下的所有元素直接复制到合并序列尾。
  • 适用场景:广泛应用于考虑稳定性的排序领域。
  • 复杂度:平均时间复杂度O(nlogn),空间复杂度O(n)。
  • 稳定性:归并排序是稳定排序,可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定性。那么,在短的有序序列合并的过程中,稳定是是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结果序列的前面,这样就保证了稳定性。所以,归并排序也是稳定的排序算法。

希尔排序


基数排序


堆排序




1 0
原创粉丝点击