将数据元素的一个任意序列,重新排列成一个按关键字有序的序列。
例:将关键字序列:52, 49, 80, 36, 14, 58, 61, 23
调整为:14, 23, 36, 49, 52, 58, 61, 80
设 Ki、Kj (1≤i≤n, 1≤j≤n, i≠j ) 分别为记录 Ri、Rj 的关键 字,且 Ki = Kj ,在排序前的序列中 Ri 领先于 Rj (即 i < j )。若在排序后的序列中 Ri 仍领先于 Rj ,则称所用的排序方法是稳定的;反之,则称所用的排 序方法是不稳定的。
例:设排序前的关键字序列为:52, 49, 80, 36, 14, 58, 36, 23
若排序后的关键字序列为:14, 23, 36, 36, 49, 52, 58, 80 则排序方法是稳定的。
若排序后的关键字序列为:14, 23, 36, 36, 49, 52, 58, 80, 则排序方法是不稳定的。
若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序;
反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中完成,则称此类排序问题为外部排序。
直接插入排序,希尔排序,直接选择排序,堆排序,冒泡排序,快速排序,归并排序,基于链式队列和顺序队列的基数排序等。在之后的几章博客中,我会着重的讲解他们具体的工作原理和使用方法。
我们会通过讨论他们的时间复杂度,空间复杂度,以及他们是否稳定这几方面来学习这些排列方法。
(1)从平均时间性能而言,快速排序最佳,其所需时间最省,但快速排序在最坏情况下的时间性能不如堆排序和归并排序。而后两者相比较的结果是,在n较大时,归并排序所需时间较堆排序省,但它所需的辅助存储量最多。
(2)简单排序包括除希尔排序之外的所有插入排序,冒泡排序和简单选择排序,其中以直接插入排序为最简单,当序列中的记录“基本有序”或n值较小时,它是最佳的排序方法,因此常将它和其它的排序方法,诸如快速排序、归并排序等结合在一起使用。
(3)基数排序的时间复杂度也可写成O(d·n)。因此,它最适用于n值很大而关键字较小的序列。若关键字也很大,而序列中大多数记录的“最高位关键字”均不同,则亦可先按“最高位关键字”不同将序列分成若干“小”的子序列,而后进行直接插入排序。
(4)从方法的稳定性来比较,基数排序是稳定的,所有时间复杂度为O(n2)的简单排序法(除简单选择)也是稳定的,而快排、堆排序和希尔排序等时间性能较好的排序方法都是不稳定的。一般来说,排序过程中的“比较”是在“相邻的两个记录关键字”间进行的排序方法是稳定的。
本章讨论的各种排序方法,其最坏情况下的时间复杂度或为O(n2),或为O(nlogn),其中O(n2)是它的上界,那么O(nlogn)是否是它的下界,也就是说,能否找到一种排序方法,它在最坏情况下的时间复杂度低于O(nlogn)呢?
对n个关键字进行排序,可能得到的结果有n!种,由于含n!个叶子结点的二叉树的深度不小于log2(n!)+1。对n个关键字比较的次数至少为log2(n!)次。
根据斯蒂林近似公式 log2(n!)≈nlog2n。
因此,基于关键字比较的排序方法,最快的时间复杂度为O(nlogn)。
对n个元素排序的决策树必然有n!片树叶(因为n个数有n!种不同的大小关系),所以决策树的深度至少是log(n!),即至少需要log(n!)次比较。
而 log(n!)=logn+log(n-1)+log(n-2)+…+log2+log1
>=logn+log(n-1)+log(n-2)+…+log(n/2)
>=(n/2)log(n/2)
>=(n/2)logn-n/2
=O(nlogn)
>=(n/2)logn-n/2
=O(nlogn)
所以只用到比较的排序算法最低时间复杂度是O(nlogn)
在之后的博客中,会详细的讲解每一个排序,大家可以持续关注,有问题的地方欢迎大家提出。