编程语言
首页 > 编程语言> > BFPRT算法

BFPRT算法

作者:互联网

在一大堆数中求其前k大或前k小的问题,简称TOP-K问题。而目前解决TOP-K问题最有效的算法即是BFPRT算法,其又称为中位数的中位数算法,该算法由Blum、Floyd、Pratt、Rivest、Tarjan提出,最坏时间复杂度为O(n)O(n)O(n)。

在首次接触TOP-K问题时,我们的第一反应就是可以先对所有数据进行一次排序,然后取其前k即可,但是这么做有两个问题:
(1):快速排序的平均复杂度为O(nlogn)O(nlogn)O(nlogn),但最坏时间复杂度为O(n2)O(n^2)O(n
2
),不能始终保证较好的复杂度。
(2):我们只需要前k大的,而对其余不需要的数也进行了排序,浪费了大量排序时间。

除这种方法之外,堆排序也是一个比较好的选择,可以维护一个大小为k的堆,时间复杂度为O(nlogk)O(nlogk)O(nlogk)。

那是否还存在更有效的方法呢?受到快速排序的启发,通过修改快速排序中主元的选取方法可以降低快速排序在最坏情况下的时间复杂度(即BFPRT算法),并且我们的目的只是求出前k,故递归的规模变小,速度也随之提高。下面来简单回顾下快速排序的过程,以升序为例:
(1):选取主元(首元素,尾元素或一个随机元素);
(2):以选取的主元为分界点,把小于主元的放在左边,大于主元的放在右边;
(3):分别对左边和右边进行递归,重复上述过程。

二:BFPRT算法过程及代码
BFPRT算法步骤如下:
(1):选取主元;
  (1.1):将n个元素划分为⌊n5⌋⌊\frac n5⌋⌊
5
n

⌋个组,每组5个元素,若有剩余,舍去;
  (1.2):使用插入排序找到⌊n5⌋⌊\frac n5⌋⌊
5
n

⌋个组中每一组的中位数;
  (1.3):对于(1.2)中找到的所有中位数,调用BFPRT算法求出它们的中位数,作为主元;
(2):以(1.3)选取的主元为分界点,把小于主元的放在左边,大于主元的放在右边;
(3):判断主元的位置与k的大小,有选择的对左边或右边递归。

上面的描述可能并不易理解,先看下面这幅图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sVeP1uIY-1584174897186)(http://oi0fekpsr.bkt.clouddn.com/BFPRT1.png)]

BFPRT()调用GetPivotIndex()和Partition()来求解第k小,在这过程中,GetPivotIndex()也调用了BFPRT(),即GetPivotIndex)和BFPRT()为互递归的关系。
————————————————
版权声明:本文为CSDN博主「LaoJiu_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/laojiu_/article/details/54986553

标签:复杂度,中位数,主元,算法,BFPRT,排序
来源: https://www.cnblogs.com/hubowen1/p/12920176.html