1、插入排序
for i = 2:n, for (k = i; k > 1 and a[k] < a[k-1]; k--) swap a[k,k-1] → invariant: a[1..i] is sorted end
最差效率: O(n2) 倒序的时候 如把abcd排成dcba
最好效率:O(n) 顺序的时候.
额外空间O(1),需要一个额外的空间.
排序稳定性:属于稳定的排序算法.(两个元素相等时排序前后相对位置不变)
因此,该算法如果能使用在预知串是基本有序的情况下是非常有潜力的.在合并排序和希尔排序中就结合了这个特点,提高算法效率.
2、选择排序
for i = 1:n, k = i for j = i+1:n, if a[j] < a[k], k = j → invariant: a[k] smallest of a[i..n] swap a[i,k] → invariant: a[1..i] in final position end
无论是什么情况,其效率都保持在O(n2).
额外空间O(1),需要一个额外的交换空间.
排序稳定性:属于不稳定的排序算法.
出名是有理由的,尽管在效率上不怎么好看,但是留意一下,它产生的swap最多时也就是n-1次.在这一点上优于其他排序的,因此,在交换的动作比较耗时的情况下,该算法还是有用武之地的.
3、冒泡排序
for i = 1:n, swapped = false for j = n:i+1, if a[j] < a[j-1], swap a[j,j-1] swapped = true → invariant: a[1..i] in final position break if not swapped end
效率也是O(n2).
额外空间O(1).
稳定排序
没想到有什么地方好用的...估计是名字好记,所以才出名的.(如果你有好的想法,请一定要告诉我)
4、希尔排序
h = 1 while h < n, h = 3*h + 1 //构造一个增量序列, while h > 0, h = h / 3 for k = 1:h, insertion sort a[k:h:n]//一般化的插入排序,表示增量为h的插入排序 → invariant: each h-sub-array is sorted end
效率和(增量序列/源排序序列)有关.(这里为O(n3/2),具体怎么算出来的我也没搞清楚,有机会会补上来),在基本有序的情况下能达到O(n·lg(n))。
额外空间O(1)
虽然是基于插入排序的,但是是非稳定的排序
相比上面三种排序,在平均效率上有一定地提高,但总的来说还是属于比较低效的算法.
5、归并排序
# split in half m = n / 2 # recursive sorts sort a[1..m] sort a[m+1..n] # merge sorted sub-arrays using temp array b = copy of a[1..m] i = 1, j = m+1, k = 1 while i <= m and j <= n, a[k++] = (a[j] < b[i]) ? a[j++] : b[i++] → invariant: a[1..k] in final position while i <= m, a[k++] = b[i++] → invariant: a[1..k] in final position
效率:属于即使在最坏情况下也不会低于O(nlogn)的高效排序。具体过程见http://my.oschina.net/daxia/blog/91577
额外空间:O(n),该算法的最不好的地方就是它的额外空间比较大。
稳定排序,在底层使用的是插入排序,然后在归并过程也没有改变相同元素顺序.
6、快速排序
# choose pivot swap a[1,rand(1,n)] # 2-way partition k = 1 for i = 2:n, if a[i] < a[1], swap a[++k,i] swap a[1,k] → invariant: a[1..k-1] < a[k] <= a[k+1..n] # recursive sorts sort a[1..k-1] sort a[k+1,n]
如其名:快速排序,虽然在最坏的情况下它可能会退化到O(n2),但是在大多随机情况下它的速度都逼近O(nlogn),因此,它是一个O(nlogn)的排序算法.
额外空间O(1).
不稳定排序
快速排序在处理内层循环时的效率非常高,使得在处理随机排列的数组时,速度要比合并排序和堆排序快.另外除了二路的平均分区,还有更加高效的三路平均分区-》http://www.sorting-algorithms.com/quick-sort-3-way
7、堆排序
# heapify for i = n/2:1, sink(a,i,n) → invariant: a[1,n] in heap order # sortdown for i = 1:n, swap a[1,n-i+1] sink(a,1,n-i) → invariant: a[n-i+1,n] in final position end # sink from i in a[1..n] function sink(a,i,n): # {lc,rc,mc} = {left,right,max} child index lc = 2*i if lc > n, return # no children rc = lc + 1 mc = (rc > n) ? lc : (a[lc] > a[rc]) ? lc : rc if a[i] >= a[mc], return # heap ordered swap a[i,mc] sink(a,mc,n)
效率:O(nlogn)
一个额外空间O(1)
不稳定排序
有针对随机文件的计时实验指出,堆排序比快速排序运行的慢,但是和合并排序还是有竞争力的.
参考和动画演示: http://www.sorting-algorithms.com
参考书籍:《算法设计与分析基础》和《数据结构》严蔚敏/吴伟明 版