各排序算法的时间复杂度分析及稳定性分析

何为稳定性

稳定的排序算法会使原本具有相等键值的记录维持相对次序。即一个排序算法如果是稳定的,那么当有两个相等键值的记录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) --更改了原来的次序
则第一种排序方法是稳定的,第二种则是不稳定的。

各排序算法的稳定性

各排序算法的时间复杂度分析及稳定性分析_第1张图片


何为时间复杂度

时间复杂度是一个函数,用来描述该算法的运行时间。
表示的是同一个问题用不同算法解决的时间开销–即效率。
时间复杂度越低,该算法的性能越好;防止则性能越差,效率越低。

各排序算法的时间复杂度分析

 插入排序

  最差情况即为每条记录都必须移动到数组的顶端–逆序的。这时比较次数为:第一次执行for为1,第二次为2,类推。则总比较次数为

  最佳情况就是关键码按照从小到大的顺序排序,仅仅一个for循环就可退出,总比较次数是 n-1 次,即外层for的循环次数。则此时的时间代价是
  平均情况下,分析有点类似最差情况,显然两个for都是需要循环的。经测定,平均情况下的时间代价约是最差情况的一半,大概是n^2÷4。仍然是

 冒泡排序

  分析冒泡排序很简单,无需考虑分布情况,内层for的循环比较次数总会是 i ,因此时间代价为

  于是冒泡排序的最佳、平均、最差情况运行时间几乎是相同的,时间代价都为

 选择排序

  对于选择排序,每次都是从未排序的序列选最小的关键值码,接着是次关键值码,依次类推。因此比较次数还是

  故选择排序的最佳、平均、最差情况的时间代价都为

 shell排序

  希尔排序与交换排序思想的不同之处在于,希尔排序是在不相邻的记录之间进行比较交换。利用了插入排序的最佳时间代价特性。最差的情况下希尔排序也比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)的时间代价。
  因此基数排序的最佳、平均、最差情况的时间代价都为

你可能感兴趣的:(数据结构)