稳定的排序算法会使原本具有相等键值的记录维持相对次序。即一个排序算法如果是稳定的,那么当有两个相等键值的记录A和B,且在原本的列表中A出现在B前,那么排序后的A也是出现在B之前。
如对一串键值进行排序,以Key为排序次序:
(6,c),(4,r),(4,f),(1,h),(8,x)
此时,可以有两种排序的结果:
(1,h),(4,r),(4,f),(6,c),(8,x) --维持了原来的次序
(1,h),(4,f),(4,r),(6,c),(8,x) --更改了原来的次序
则第一种排序方法是稳定的,第二种则是不稳定的。
时间复杂度是一个函数,用来描述该算法的运行时间。
表示的是同一个问题用不同算法解决的时间开销–即效率。
时间复杂度越低,该算法的性能越好;防止则性能越差,效率越低。
最差情况即为每条记录都必须移动到数组的顶端–逆序的。这时比较次数为:第一次执行for为1,第二次为2,类推。则总比较次数为
最佳情况就是关键码按照从小到大的顺序排序,仅仅一个for循环就可退出,总比较次数是 n-1 次,即外层for的循环次数。则此时的时间代价是 平均情况下,分析有点类似最差情况,显然两个for都是需要循环的。经测定,平均情况下的时间代价约是最差情况的一半,大概是n^2÷4。仍然是分析冒泡排序很简单,无需考虑分布情况,内层for的循环比较次数总会是 i ,因此时间代价为
于是冒泡排序的最佳、平均、最差情况运行时间几乎是相同的,时间代价都为对于选择排序,每次都是从未排序的序列选最小的关键值码,接着是次关键值码,依次类推。因此比较次数还是
故选择排序的最佳、平均、最差情况的时间代价都为 希尔排序与交换排序思想的不同之处在于,希尔排序是在不相邻的记录之间进行比较交换。利用了插入排序的最佳时间代价特性。最差的情况下希尔排序也比O(n^2)要好。
平均情况下,可不加证明的承认(我不行)Shell排序的时间代价为
归并排序基于分而治之的思想,是递归的。归并排序的时间代价并不依赖于待排序数据的相对顺序。不妨设i为两个要归并子数组的总长度,归并过程需要花费O(i)时间。而待排序的数组一直不断的被分成两半,直到子数组长度为1;然后再逐个合并。因此,对于待排序的数组长度为n时,递归的深度是log n。第一层递归可看成对长度为n的数组的排序,第二层递归是对长度为n/2的数组的排序,……,最后一层是对长度为1的子数组的排序。显然,对于n个长度为1的子数组归并需要O(n),对n/2个长度为2的子数组归并需要O(n),……因此,总时间代价为
故归并排序的最佳、平均、最差情况的时间代价都为最差情况轴值没有很好的划分数组,即一个子数组中没有结点,二另一个有n-1个节点。那么总时间代价为
最佳情况就是每个轴值都将数组划分成相等长度的两部分。最佳情况下,要划分log n次。每次划分的时间开销为O(n),则此时的时间代价是 平均情况下,是介于最佳与最差之间,经过推算算出来的平均时间代价也是(感兴趣的同学自己算算) 堆排序的整棵树都是平衡的。在平均情况下比快速排序要慢一个常数因子,但堆排序更适合于外排序,用于处理那些数据集太大而不适合在内存中排序的情况。
建立堆需要花费O(n)的时间,并且在n次取堆的过程中,每次需要花费O(log n)的时间,并且与数据排列无关。
因此堆排序的最佳、平均、最差情况的时间代价都为
分配排序很出色,但只能用于满的数组(0~n-1)排序!
无论初始数组的关键码顺序如何,都只需要O(n)的时间代价。
因此堆排序的最佳、平均、最差情况的时间代价都为
基数排序通过将数据分发到数组中并将之连接起来。其中将元素放到数组中花费的时间代价是O(n),而对于k个键值下,则需要O(kn)的时间复杂度。
无论初始数组的关键码顺序如何,都只需要O(kn)的时间代价。
因此基数排序的最佳、平均、最差情况的时间代价都为