BFPRT算法详细解析

BFPRT算法是一种选择算法,旨在优化快速排序中的分区过程。通过选取五分位数的中位数作为基准值,减少最坏情况的发生。算法步骤包括分组、寻找中位数、递归寻找中位数的中位数,最终确定基准值并划分数组。相比于快速排序,BFPRT算法能更均匀地划分数据,提高效率。时间复杂度分析表明其最坏情况下为O(n),优于快速排序的最坏情况。
摘要由CSDN通过智能技术生成

概念

BFPRT算法即是选取中位数的中位数的方式,找出数组n个元素中第k大的数。我们可以根据快速排序得到该值,但是快速排序的平均复杂度为O(nlog(n)),最坏时间复杂度为O(n^2)。而堆排序也是一个较好的方法,维护一个大小为k的堆,时间复杂度为O(nlog(k))。而BFPTR算法。它的最坏时间复杂度为O(n)

BFPRT算法原理

之前讲过一篇文章关于快速排序文章,我们便继续从那里开始引入。快速排序的大致过程如下:

  • 先从序列中选取一个数最为基准数
  • 将比这个数大的数全部放到它的右边,把小于或者等于它的数全部放到它的左边

一趟快速排序也叫做Partion,即将序列划分为两部分,一部分比基数小,另一部分比基数大,然后再进行分治的过程,每一次Partion不一定都能保证划分得很均匀,所以最坏情况下得时间复杂度不能保证总是为O(nlog(n))。而在BFPTR算法中,仅仅是改变了快速排序Partion中的pivot值的选取,在快速排序中,我们始终选择第一个元素或者最后一个元素作为Pivot,而在BFPTR算法中,每次选择五分中位数的中位数作为pivot`,这样做的目的就是使得划分比较合理,从而避免了最欢情况的发生。算法步骤如下:

  • 将n个元素划为⌊n/5⌋组,每组5个,至多只有一组由n mod 5 个元素组成。
  • 寻找⌈n/5⌉个组中每一个组的中位数,这个过程可以用插入排序。
  • 对步骤2中的⌈n/5⌉个中位数,重复步骤1和步骤2,递归下去,直到剩下一个数字。
  • 最终剩下的数字即为pivot,把大于它的数全放左边,小于等于它的数全放右边。
  • 判断pivot的位置与k的大小,有选择的对左边或右边递归。

下面以一个例子具体分析,设A = { {8,33,17,51,57}},{49,35,11,25,37},{14,3,2,13,52},{12,6,29,32,54},{5,16,22,23,7}},数组A包含25个元素。首先,将数组A分成 5组,每组5个元素然后,对每组元素由小到大排序再按每组的中位数由小到大排 序得到如图2.2所示的数据方阵由各组中位数组成 一个中位数数组,如图2.2 中中间长条矩形中的元素取中位数数组的中位数,得到中位数的中位数mm=29. 最后以29为基准,将数组A划分成三部分: A1 ={ala< mm}, A2 ={ala= mm} 和A3={ala> mm} .如图所示
在这里插入图片描述
图中左下角矩形中的元素均小于等千中位数的中位数mm(29), 而右上角矩形中的元素均大千等千中位数的中位数mm(29).

令A'1={ala<=mm}, A'3={ala>=mm}, 则有
|A'1|>=3⌈(⌊n/5⌋)/2⌉>=3/2⌊n/5⌋,从而可得
|A3|<=n-3/2⌊n/5⌋<=n-3/2(n/5 - 4/5)=7/10n + 1.2
类似可得
|A'1|>=3/2⌊n/5⌋
和|A1|<=7/10n + 1.2

在这里插入图片描述
如果对含有 n 个元素的数组调用BFPRT算法的计算时间复杂度为T(n),由于每组p个元素,对于p = 5, n可取44(44的取值为保证该式(7n/10)+1.2<=⌊3n/4⌋成立,当然最小值可以取到39,去掉向下取整符号,看它相应的余数最大是多少,相应的剪掉就好了,比方这里最大余数是3/4)。可以得到q = ⌈n/p⌉个中位数,且只可能有一组不是5个元素,找中位数的中位数时丢弃这一组,但不会影响最终结果,所以在第10步的计算时间复杂度为T(⌊n/5⌋)(因为丢弃了一组)。当n>=44时,不等式(7n/10)+1.2<=⌊3n/4⌋成立。从而,在该算法中第12-20步的计算时间复杂度为T(⌊3n/4⌋)。此外,算法第3-6步的时间复杂度为O(1);算法第7步时间复杂度为O(1);算法第8步和第9步的计算时间复杂度均为O(n)。从而可得到下列关于T(n)的递归方程,即,

if n<44时,T(n) <= c;
if n>44时,T(n) <= T(⌊n/5⌋) + (T⌊3n/4⌋) + cn
通过解得该递归可得到T(n) = O(n),所以是线性时间复杂度。

算法实现如下:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <algorithm>
 
using namespace std;
const int N = 10005;
 
int a[N];
 
//插入排序
void InsertSort(int a[], int l, int r
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值