快排给了我们一种快速选择数组第
k
小的思路:
这样我们消耗的时间为
E[T(n)]=E[T(k)]+cn⩽∑i=1n−1E[T(max{n−i,i})]n−1+cn
⇒E[T(n)]⩽p3n24(n−1)+cn<p3n2+n−44(n−1)+cn⩽pn⇔p>4cnn−4
当然,
n→∞
时,
p→4c
因此,我们的时间复杂度可以为
T(n)=4cn
是线性的.
但我们总是不满意,一个运行时间期望为 O(n) 的算法可以运行 O(n2) 之久,我们想要一个最坏 O(n) 的算法,这是有的:
我们考虑使快速选择算法运行时间达到 O(n2) 的原因:主元的选择.
这样,我们考虑主动为Part函数选择一个合适的主元:它应该稳定在 (nk,nt) 之间,这样我们就避免了极端情况的发生,从而使我们的快速选择能稳定下来,
我们考虑这样的启发式策略:将数组分为 nc 个相等的部分,每个部分均有 c 个元素(最后一个部分可能有不到
我们来想一想,在我们得到的
这样我们就稳定地给出了一个合适的主元
下面,我们来求合适的
首先,我们总是碰到了最坏情况:
T(n)=T(nc)+T(n−⌈c2⌉n2c)+q.c2.nc
首先:我们要保证
nc+n−⌈c2⌉n2c<n
否则我们就会得到 O(nlogn) 的时间复杂度,这不是我们所期望的;
解上述不等式,解得 c>4
设 ∀k<n 我们有 T(k)⩽pk 成立,那么对 n 我们有:
我们得到
p⩾qc2⌈c2⌉−2
最后,我们给 p 取最优值得到
我们取 c=5,c=7 都是合适的,都可以使我们的快速选择算法稳定于 O(n) ,
从而,我们得到了稳定的快速选择算法;(好累啊,休息一下).