您的位置:首页 > 其它

线性选择算法 .

2015-07-19 22:06 155 查看
在期望的线性时间内,可以找到顺序统计量,特别是中位数.

在最坏的情况下,时间依然是线性的.

选择问题定义,实际上所有处理均可以推广到集合中包含重复数值的情形。

输入:一个包含n个(不同的)数的集合A和一个数i,1<=i<=n。

输出:元素x属于A,它恰大于A中其他的i-1个元素。


1、最大值最小值

针对一个序列取得最大和最小值均需要n-1次比较。这是一个下限,确定最大值或者最小值的算法可以看作各个元素之间一场锦标赛,每次比较都是一场比赛,两个元素中较小的或者较大的获胜,除了最终的最大值和最小值,所有其他元素都需要输一次,所以n-1次是必须的。

接下来是一些比较有意思的问题,比如同时找出最小值和最大值,当然可以n-1次比较找出最大值,然后n-2次比较找出最小值,不过还是有比这个更好一点的算法,把元素两两分组,然后比较产生一个较大的值和较小的值,然后较大的值中产生最大值,较小的值中产生最小值,此时需要比较操作的次数至多3|_n/2_|。

还有一个比较问题是同时找出最大第二大或者最小次小元素的比较次数,简单的当然是2n-3,不过也有一个分组的方法能够达到n+lgn-2的比较次数。比较方法如下:


选择问题定义,实际上所有处理均可以推广到集合中包含重复数值的情形。

输入:一个包含n个(不同的)数的集合A和一个数i,1<=i<=n。

输出:元素x属于A,它恰大于A中其他的i-1个元素。


1、最大值最小值

针对一个序列取得最大和最小值均需要n-1次比较。这是一个下限,确定最大值或者最小值的算法可以看作各个元素之间一场锦标赛,每次比较都是一场比赛,两个元素中较小的或者较大的获胜,除了最终的最大值和最小值,所有其他元素都需要输一次,所以n-1次是必须的。

接下来是一些比较有意思的问题,比如同时找出最小值和最大值,当然可以n-1次比较找出最大值,然后n-2次比较找出最小值,不过还是有比这个更好一点的算法,把元素两两分组,然后比较产生一个较大的值和较小的值,然后较大的值中产生最大值,较小的值中产生最小值,此时需要比较操作的次数至多3|_n/2_|。

还有一个比较问题是同时找出最大第二大或者最小次小元素的比较次数,简单的当然是2n-3,不过也有一个分组的方法能够达到n+lgn-2的比较次数。比较方法如下:


RANDOMIZED-SELECT(A,p,r)
if p = r
then retrun A[p]
q= RANDOMIZED-PARTITION(A,p,r)
k= q-p+1
if i = k
then return A[q]
else if i<k
return RANDOMIZED-SELECT(A,p,q-1,i)
else
return RANDOMIZED-SELECT(A,q+1,r,i-k)


RANDOMIZED-PARTITION(A,p,r)
i=RANDOM(p,r)
exchange A[r],A[i]
return PARTITION(A,p,r)
PARTITION(A,p,r)
x=A[r]
i=p-1
for j=p to r-1
do if A[j]<=x
i++
exchange A[i],A[j]
exchange A[i+1],A[r]
return i+1


上面方法的期望时间是线性的,数学证明比较复杂就省略了。

最坏情况线性时间

上面期望时间线性是因为可能存在某种最坏的情况,每次分割元的位置都是导致一边没有元素,这样就不能够达到线性了,接下来的一些预先工作就是避免这种情况发生。

算法SELECT通过执行下列步骤来确定一个有n个元素的输入数组中的第i个小的元素。


1、将输入数组的n个元素划分为n/5组,每组5个元素,且至多有一个组由剩下的n mod 5个元素组成。

2、寻找n/5个组中每一组的中位数。(方法首先对每组中的元素进行插入排序,然后从排序过的序列中选出中位数)

3、对第2步中找出的n/5个中位数,递归调用SELECT找出其中位数x。(如果有偶数个中位数,根据约定,x是下中位数。)

4、利用修改过的PARTITION过程,按中位数的中位数x对输入数组进行划分。让k比划分低区的元素多1,所以x是第k小的元素,并且有n-k个元素在划分的高区。

5、如果i=k,则返回x,否则,如果i
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: