排序算法大全

361 阅读4分钟

这是我参与8月更文挑战的第17天,活动详情查看:8月更文挑战

插入排序

  • 每次将一个待排序的记录按其关键字大小'插入'到前面'已排好序的子序列中',类似于扑克牌的插入
  • 例如 n=6,数组R的六个排序码分别为:17,3,25,14,20,9。它的直接插入排序的执行过程

image.png 希尔排序

先将整个待排序的记录序列分割成为若干子序列分别进行'直接插入排序',待整个序列中的记录“基本有序”时,
再对全体记录进行依次直接插入排序。假设增量为5,则i,i+5....;下图增量为5

image.png

交换排序

  • 对待排序序列从后向前(从下标较大的元素开始),'依次比较相邻元素'的排序码,若发现'逆序则交换',
  • 使排序码较小的元素逐渐从后部移向前部,就象水底下的气泡一样逐渐向上冒。
  • 例如,n=6,数组R的六个排序码分别为:17,3,25,14,20,9。下面图给出冒泡排序算法的执行过程。

image.png

快速排序

  • 取待排序序列中的某个元素(一般第一个元素)作为基准,通过一趟排序,将待排元素分为'左右两个子序列',
  • '左子序列元素'的排序码均'小于或等于基准元素'的排序码,
  • '右子序列'的排序码则'大于基准元素'的排序码,然后分别对两个子序列继续进行快速排序,直至整个序列有序。
  • 元素的比较和交换是从两端向中间进行的,排序码较大的元素一次就能够交换到后面,排序码较小的记录一次就能够交换到前面,
  • 记录每次移动的距离较远,因而总的比较和移动次数较少。 例如,给定排序码为:(46,55,13,42,94,05,17,70)

一次划分

image.png

选择排序

简单选择排序

基本思想是:第一次从'array[0]~array[n-1]'中'选取最小值',与'array[0]'交换,
第二次从'array[1]~array[n-1]'中选取最小值,与'array[1]'交换,
第三次从'array[2]~array[n-1]'中选取最小值,与'array[2]'交换,…
例如,给定n=8,数组R中的8个元素的排序码为:'(8,3,2,1,7,4,6,5)'

image.png

堆排序

  • 将排序码k1,k2,k3,…,kn表示成'一棵完全二叉树',然后从树的最后一个非叶结点开始筛选,
  • 使由该结点作根结点组成的子二叉树符合堆的定义,然后从第n/2 -1个排序码重复刚才操作,直到第一个排序码止。
  • 将堆中第一个结点(二叉树根结点)和最后一个结点的数据进行交换(k1与kn),
  • 再将k1kn-1重新建堆,然后k1和kn-1交换,再将k1kn-2重新建堆,然后k1和kn-2交换,
  • 如此重复下去,每次重新建堆的元素个数不断减1,直到重新建堆的元素个数仅剩一个为止。

image.png

归并排序

  • 将两个(或两个以上)有序表合并成一个'新的有序表',即把待排序序列'分为若干个子序列',
  • 每个子序列是'有序的'。然后再把有序子序列合并为整体有序序列。

image.png

基数排序

  • 数排序将要排序的元素分配至某些“桶”中,以达到排序的作用
  • 属于稳定性的排序,其时间复杂度为O(nlog(r)m),其中r为所采取的基数,而m为堆数

各个排序比较

'不稳定''快选堆希'(快速排序、选择排序、堆排序、希尔排序)
'稳定''插冒归计基'(简单插入排序、冒泡排序、归并排序、计数排序、基数排序)
移动次数和关键字顺序无关的排序:
'一堆(堆排序)海龟(归并排序)选(选择排序)基(基数排序)友'--->'堆排序、归并排序、选择排序、基数排序'