BFPRT演算法(中位數之中位數)初窺 五

2021-06-03 18:59:35 字數 2002 閱讀 5910

bfprt演算法的作者是5位真正的大牛(blum 、 floyd 、 pratt 、 rivest 、 tarjan),該演算法入選了在stackexchange上進行的當今世界十大經典演算法,而演算法的簡單和巧妙頗有我們需要借鑑學習之處。

bfprt解決的問題十分經典,即從某n個元素的序列中選出第k大(第k小)的元素,通過巧妙的分析,bfprt可以保證在最壞情況下仍為線性時間複雜度。

當我們面對這一問題時,首先想到的直觀方法一般為k次(假設kfunction select(list[1..n], k)

for i from 1 to k

minindex = i

minvalue = list[i]

for j from i+1 to n

if list[j] < minvalue

minindex = j

minvalue = list[j]

swap (list[i],list[minindex])

return list[k]

通過k次迴圈,方法可以依次選擇出最小的k個值,該方法時間複雜度為o(kn)。當k較小時,方法的效率較為優秀,但當k->n/2時,方法複雜度變為了o(n^2)

思考該方法中多餘的能量支出,方法按順序輸出了最小的k個元素,而這並不是我們需要的,如果我們只獲得哪些值比該值小,而不對比其小的進行排序,演算法代價將大幅下降。由於上面的方法用了選擇排序的思想,那麼利用快速排序的思想進行選擇容易想到quickselection。

每次選擇某一pivot,通過快速排序的思路,我們可以獲得比pivot小的所有數和比其大的所有數,由此可以選出所需的kth值在哪以區間呢,並在該區間內再次使用quickselection。方法的偽碼如下

function select(list, left, right, k)

if left = right // if the list contains only one element

return list[left]  // return that element

select pivotindex between left and right

pivotnewindex := partition(list, left, right, pivotindex)

pivotdist := pivotnewindex – left + 1

if pivotdist = k

return list[pivotnewindex]

else if k < pivotdist

return select(list, left, pivotnewindex - 1, k)

else

return select(list, pivotnewindex + 1, right, k - pivotdist)

如quicksort一樣,該方法在實際應用中有較好的效果,但在某些特殊情況中,由於pivot的選擇,會出現一些效率極端不好的情況,例如某倒排表。

bfprt是一種獲得較優秀pivot的方法,方法的思路是使獲得的pivot能夠較為有效的對整個資料進行分割,並在其中利用暫存器的快速計算能力將問題拆分為代價極小的子問題。

方法的思路為:將元組分為n/5個5元的小陣列,並對每組求中位數,在長度為n/5的序列中,求其中位數,該中位數的中位數保證了至少30%的資料在其一側,由此保證了pivot的有效性(如圖,改圖來自wikipedia)

關於為何利用5作為小元組大小,我的想法是與暫存器的數量和運算有關。

由於pivot的有效分割和5元組中位數易求性,從n元組中取值的代價t(n)<=t(n/5)+t(7n/10)+o(n),t(n/5)是為中位數取中位數的時間,o(n)是遍歷序列並求得中位數數列的時間.

設t(n)=cn,此處c可以不是常熟,若c與n成線性關係,則t(n)=o(n^2),設遍歷時間為an,a為常數

則有 t(n)<=c(n/5)+c(7n/10)+an=c(9/10*n)+an //此處,低次已被省略低次項

求得c<=10a 故c為常數,與n無關

且t(n)至少為o(n),

綜上,該演算法為一線性演算法

BFPRT(中位數的中位數)演算法

又稱為 中位數的中位數演算法 該演算法由 blum floyd pratt rivest tarjan 在1973年提出,最壞時間複雜度為o n 最差的空間複雜度為o logn 演算法步驟 1 將 n 個元素劃分為 n 5 個組,每組 5 個元素,若有剩餘,捨去 2 使用排序方法找到 n 5 個組中...

中位數的中位數

參照王曉東的演算法設計 中位數的中位數,即將一串數分成n段,求其排好序了的中間那個數,再把這些所有中位數再求一次中位數。for int i 0 i r p 4 5 i 找中位數的中位數,r p 4即上面所說的n 5 int x lineselect a,p,p r p 4 5,r p 4 10 線性...

樹狀陣列 二分 中位數之中位數

給出乙個長度為 n 的序列 a 首先求出其所有區間的中位數,將這些中位數構成的集合記為 s 求 s 中所有數的中位數。此題中位數指 有 n 個數,第 left lfloor frac right rfloor 1 個數即為中位數。資料範圍 1 leq n leq 10 5,1 leq a i leq...