[翻译]几种常用的基本排序算法
排序问题的种类繁多,因此相应的算法也是层出不穷,现在介绍下几种常用的算法。
我们知道快速排序是最快的排序算法之一,但有些排序算法是效率很低的,不建议使用在程序之中,比如说冒泡排序,交换排序,插入排序。
冒泡排序:交换两个相邻的元素,如果他们不是正确的顺序,一直循环下去直到整个序列都已经排好。这是一个很慢的排序算法。
选
择排序:查找最大的元素,把它放在序列的末尾(和末尾的数进行交换),然后递归的对剩余的元素进行排序,直到整个序列都排好。选择排序在数据移动次数上优
于插入排序,但选出最大数还需要n-1次比较,故总的比较次数仍为O(n2),而借助二叉搜索的插入排序只需O(N log
N)次。这也是一个很慢的排序算法。
插入排序:扫描连续元素,依次将没有排序的元素插入适当的位置。对于少量数据是快的,但是大量数据
会非常慢。我们可以改进算法的性能,对n-1个已排序的数用二叉搜索来确定插入第n个数的正确位置。这样没插入一个数的搜索过程就进行了O(log
N)次比较。但是数据的移动次数还是没有减少,所以算法仍然是平方级的。
我们还可以用平衡树来提高插入或选择排序的性能。
快速排序:将序列划分成两个部分,第一部分的所有元素都小于等于支点元素,第二部分的所有元素都大于等于支点元素。递归的对这两个部分元素进行排序。快速排序思想把较多的时间用在“分”上,而把较小时间用在“治”上。
支
点元素选取问题,如果支点永远将序列分成两个相等的部分,那么时间复杂度为 O(n log
n)。即使条件弱的多,也能得到相同的性能。然而若支点非常靠近序列的某一端,速度将减慢。例如,如果支点是序列中最小的数,那么首先分割操作需要n-1
次比较才能把支点放在正确的位置上。在最坏的情况下运行时间会增加到O(n2)。
快速排序在平均时间上速度最快,主要原因不仅在于优雅的分治算法,还因为有许多数都跟同一个数(支点)进行比较。于是可以把支点存在某个寄存器中,而不必反复从内存中读取。
合并排序:和快速排序相似,是一种分治算法。是先进行长度为1的排序,再合并成长度为2的排序,递归直到长度为n。而快速排序是先进行划分,然后排序,不需要额为的空间,合并排序需要N的额外空间。是一种稳定的排序。
希尔排序:思想是将序列变成多维的,对每维的数据进行排序。效果是序列被部分的排序。这样一直处理下去,但是每次处理的排列会变窄。到最后一次排序,将是所有元素。每一步,被排序的序列是增加的,直到最后一次排序。
堆排序:堆排序是一种速度较快的排序算法。在最坏情况下的运行时间是O(n log n),堆排序是一种原地置换排序算法。算法的主要部分是建堆,分为自顶而下和自底向上两种。
任何基于比较的算法的平均运行时间都是O(n log n)。
参考网站:
http://www.inf.fh-flensburg.de/lang/algorithmen/sortieren/algoen.htm
http://www.cs.ubc.ca/~harrison/Java/sorting-demo.html
http://atschool.eduweb.co.uk/mbaker/sorts.html
http://www.concentric.net/~ttwang/sort/sort.htm
