1.问题描述
在一个由n个元素组成的集合中,第i
个顺序统计量是该集合中第i
小的元素。例如:在一个元素集合中,最小值是第1个顺序统计量,最大值是第n个顺序统计量。用非形式化的描述来说,一个中位数是它所属集合的“中点元素”。当n为奇数时,中位数是唯一的,位于i = (n + 1) / 2
处。当n为偶数时,存在两个中位数,分别位于i=n/2
和i = n/2+1
处。
输入:一个包含n个(互异的)数的集合A和一个整数i
, 1 <= i <= n。
输出:元素x
属于A,且A中恰好有i-1
个其他元素小于它。
2.算法实现
选择算法-伪代码:
FUNCTION Randomized_Select(A, p, r, i)
if p == r
return A[p]
q = Randomized_Partition(A, p, r)
k = q - p + 1
if i == k
return A[q]
else i < k
return Randomized_Select(A, p, q-1, i)
else return Randomized_Select(A, q+1, r, i-k)
随机划分-伪代码:
FUNCTION Randomized_Partition(A, p, r)
q = random(p, r)
exchange A[r] with A[q]
q = p - 1
for i = p to r-1
if A[r] < A[i]
q = q + 1
exchange A[i] with A[q]
exchange A[q + 1] with A[r]
return q + 1
- 第2-3行检查递归的基本情况,即
A[p..r]
中只包含一个元素。 - 第4行调用Randomized_Partition,将数组随机划分为两个子数组
A[p..q-1]
和A[q+1..r]
,使得A[p..q-1]
中的每个元素都小于等于A[q]
,而A[q]
小于A[q+1..r]
中的每个元素。 - 第5行计算
A[p..q]
中元素的个数k。 - 第6-7行检查
A[q]
是否是第i
小的元素。 - 第8-10行要确定第
i
小的元素落在两个子数组A[p..q-1]
和A[q+1..r]
的哪一个之中。第8-9行在低区的子数组中进一步递归查找,第10行在高区的子数组中递归查找。
该算法的期望运行时间为O(n)。