bfprt演算法即是選取中位數的中位數
的方式,找出陣列n個元素中第k大的數
。我們可以根據快速排序得到該值,但是快速排序的平均複雜度為o(nlog(n)),最壞時間複雜度為o(n^2)。而堆排序也是乙個較好的方法,維護乙個大小為k的堆,時間複雜度為o(nlog(k))。而bfptr演算法。它的最壞時間複雜度為o(n)
。
之前講過一篇文章關於快速排序文章,我們便繼續從那裡開始引入。快速排序的大致過程如下:
一趟快速排序也叫做partion,即將序列劃分為兩部分,一部分比基數小,另一部分比基數大,然後再進行分治的過程,每一次partion不一定都能保證劃分得很均勻,所以最壞情況下得時間複雜度不能保證總是為o(nlog(n))。而在bfptr演算法中,僅僅是改變了快速排序partion中的pivot值的選取
,在快速排序中,我們始終選擇第乙個元素或者最後乙個元素作為pivot,而在bfptr演算法中,每次選擇五分中位數的中位數作為pivot`,這樣做的目的就是使得劃分比較合理,從而避免了最歡情況的發生。演算法步驟如下:
下面以乙個例子具體分析,設a = },,,,},陣列a包含25個元素。首先,將陣列a分成 5組,每組5個元素然後,對每組元素由小到大排序再按每組的中位數由小到大排 序得到如圖2.2所示的資料方陣由各組中位數組成 乙個中位數陣列,如圖2.2 中中間長條矩形中的元素取中位數陣列的中位數,得到中位數的中位數mm=29. 最後以29為基準,將陣列a劃分成三部分: a1 =, a2 = 和a3= .如圖所示
圖中左下角矩形中的元素均小於等千中位數的中位數mm(29), 而右上角矩形中的元素均大千等千中位數的中位數mm(29).
令a'1=, a'3=, 則有
|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
#include
#include
#include
#include
using
namespace std;
const
int n =
10005
;int a[n]
;//插入排序
void
insertsort
(int a,
int l,
int r)
a[j]
= t;}}
}//尋找中位數的中位數
intfindmid
(int a,
int l,
int r)
//處理剩餘元素
int num = r - i +1;
if(num >0)
n /=5
;if(n == l)
return l;
return
findmid
(a, l, l + n);}
//進行劃分過程
intpartion
(int a,
int l,
int r,
int p)
a[i]
= pivot;
return i;
}int
bfprt
(int a,
int l,
int r,
int k)
intmain()
/**10
72 6 57 88 60 42 83 73 48 85
5*/
另一種複雜度解釋(基於該c++**,相對好理解)
bfprt演算法的最壞時間複雜度為o(n)。設t(n)為時間複雜度,那麼很容易有如下公式
t(n) <= t(n/5) + t(7n/10) + c*n
證明:設t(n)=tn ,其中t可能是乙個常數,也可能是關於n 的函式。帶入上式
tn <= t(n/5) + t(7n/10) + cn 可推出 t<= 10c
其中 c是常數,所以 t也是常數,即t(n)<=10cn ,所以t(n) = o(n).
首先,偶數排除,因為對於奇數來說,中位數更容易計算。
如果選用3,有 t(n) <= t(n/3) + t(2n/3) + c*n,其操作元素個數還是n 。
如果選取7,9或者更大,在插入排序時耗時增加,常數 c 會很大,有些得不償失。
參考文獻:
面向資料探勘的演算法設計與分析
bfprt演算法解析
首先講一下bfprt演算法是幹嘛的?bfprt演算法是用來求陣列中第k小的元素的演算法,bfprt演算法可以在o n 時間內求出答案。對於求陣列中第k小的元素的問題,我們已經有很好的常規演算法了,這個演算法在最好的情況下時間複雜度是o n 但在最壞的情況下是o n 2 的,其實bfprt演算法就是在...
BFPRT演算法詳解
在一大堆數中求其前k大或前k小的問題,簡稱top k問題。而目前解決top k問題最有效的演算法即是bfprt演算法,其又稱為中位數的中位數演算法,該演算法由blum floyd pratt rivest tarjan提出,最壞時間複雜度為o n 在首次接觸top k問題時,我們的第一反應就是可以先...
演算法 BFPRT(線性查詢演算法)
bfprt演算法解決的問題十分經典,即從某n個元素的序列中選出第k大 第k小 的元素,通過巧妙的分 析,bfprt可以保證在最壞情況下仍為線性時間複雜度。該演算法的思想與快速排序思想相似,當然,為使得演算法在最壞情況下,依然能達到o n 的時間複雜 度,五位演算法作者做了精妙的處理。演算法步驟 1 ...