归并排序,快速排序为什么快
Posted dog250
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了归并排序,快速排序为什么快相关的知识,希望对你有一定的参考价值。
对于一个 n n n个元素的数组,必须要确定两两之间的相对顺序,假设每次都抓取不同的二元组,需要 log 2 n ! \\log_2n! log2n!次比较,由于 log 2 n ! ≈ n log 2 n \\log_2n!\\approx n\\log_2n log2n!≈nlog2n, O ( n log 2 n ) O(n\\log_2n) O(nlog2n)就是排序算法的下界。
前面几周写过一篇散文:
https://zhuanlan.zhihu.com/p/429710417
但紧接着问题就来了,到底为什么归并排序,快速排序快呢?
这里有必要澄清一下两个问题的区别:
- 归并排序,快速排序节省了哪些比较操作?
- 归并排序,快速排序为什么能节省这些操作?
上面那篇文章里,似乎回答了第一个问题,但仔细一想,发现还差点(我已经做了批注)。
虽然可以看出具体省略了哪些比较操作,但背后的原因是什么?或者换一个问题,冒泡排序到底为什么慢?
冒泡排序实际上将数组中任意两个数字都进行了一次比较,问题在于,这些比较中,有一些是没有必要的。比如:
- 比较1: a 2 < a 8 a_2<a_8 a2<a8
- 比较2: a 8 < a 19 a_8<a_19 a8<a19
- 比较3: a 2 < a 19 a_2<a_19 a2<a19
比较3还有意义吗?毫无意义!然而冒泡排序无法识别,它只是逐数字顺序比较。
对于 log 2 n ! \\log_2n! log2n!的分析,比较3是隐含在比较1和比较2两个比较中的,事实上当完成比较1和比较2后,在上面的比较结果下,比较3就没有必要了,除非比较1得出 a 2 > a 8 a_2>a_8 a2>a8或者比较2得出 a 8 > a 19 a_8>a_19 a8>a19的结论,才需要比较3。
按照排列组合分析,可天然剔除掉可传递的关联比较, log 2 n ! ≈ n log 2 n \\log_2n!\\approx n\\log_2n log2n!≈nlog2n次比较是不包括可传递的关联比较的。
接下来只要说明归并排序和快速排序的每次比较都是无关联即可,这个是显然的:
- 归并排序:实际合并之前,两个子数组从没遇见过,不可能有任何关联。
- 快速排序:左右两个子数组均按原始相对顺序和锚点比较,内部彼此无关联。
无论如何,归并排序均可达 O ( n log 2 n ) O(n\\log_2n) O(nlog2n)的时间复杂度,对于快速排序,在最理想情况下,也可达到,即便是平均情况,离最理想情况也不远。
冒泡排序的算法本身就如此定义,随排序进行,未排序序列趋于有序,但排序过程无法识别哪些比较是不必要的,从信息论的角度,大概率的非必要比较依然要进行,这些比较带来的信息量无疑很小,这就是低效的根源,反过来,归并排序和快速排序依偎着比较排序的下界,这就是它们快的根源。
log n ! ≈ n log n \\log n!\\approx n\\log n logn!≈nlogn事实上就是排序的最大熵,自然就是排序操作的下界。在没有预假设的情况下, n n n个数组的序列一共有 n ! n! n!种,升序(或者降序)只是其中一种,它的概率为 1 n ! \\dfrac1n! n!1,排序信息熵为:
H = − ∑ i − 1 n ! 1 n ! log 2 1 n ! = log 2 n ! ≈ n log n H=-\\sum\\limits_i-1^n!\\dfrac1n!\\log_2\\dfrac1n!=\\log_2n!\\approx n\\log n H=−i−1∑n!n!1log2n!1=log2n!≈nlogn
时间复杂度就是信息熵的度量,引入新的预设,信息熵必然减小,冒泡排序随着排序的进行,将引入新的预设,而归并排序和快速排序在排序过程中一直保持最开始的预设,保持比较操作的无关联性。
浙江温州皮鞋湿,下雨进水不会胖。
以上是关于归并排序,快速排序为什么快的主要内容,如果未能解决你的问题,请参考以下文章