思想:首先對整個陣列進行劃分,利用partition函式,以陣列中某個數為基準(這裡以首項為標準)將陣列劃分為兩部分——左邊部分的所有數都小於基準,右邊部分都大於基準,並返回基準數的下標值。
然後,如果要找到第k小個數,就將k的大小與陣列左半邊元素的個數(若為 j,包括基準)進行比較,如果k小於j,則對左邊部分進行遞迴,找第k小個數;若k大於j,則對右邊部分進行遞迴,找第k減去j個小數。
#includeusing namespace std;
templateint partition(t a, int l, int r)
a[l] = a[j];
a[j] = x;
return j;
}templatet select(t a, int left, int right, int k)
int main()
分析一下partition函式:
以陣列 a = 為例,首先以3為基準,令x=a[0](一般寫為x=a[left], left為陣列左邊的最小下標值),i= 0,
j=6+1(最大下標值加一),接著進迴圈。i自增1,判斷a[i]是否小於x,若小於則繼續往下判斷,否則退出迴圈。然後,j自減1,判斷a[j]是否大於x,若大於繼續迴圈,否則退出迴圈。可知第一次退出時,i=2,j=3。然後交換a[i]與a[j]的值,陣列變為,繼續迴圈,直到i>=j時退出迴圈,可知退出迴圈時i=3,j=2。將a[0]與a[j]的值交換,返回下標j旳值。陣列變為
左半部分(下標值小於2的部分)都小於基準x,即3,右邊都大於3。
例如,若ε=9/10,演算法遞迴呼叫所產生的子陣列的長度至少縮短1/10。所以,在最壞情況下,演算法所需的計算時間t(n)滿足遞迴式t(n)≤t(9n/10)+o(n) 。由此可得t(n)=o(n)。
步驟:(1)將n個輸入元素劃分成n/5(向上取整)個組,每組5個元素,最多隻可能有乙個組不是5個元素。用任意一種排序演算法,將每組中的元素排好序,並取出每組的中位數,共n/5(向上取整)個。
(2)遞迴呼叫select來找出這n/5(向上取整)個元素的中位數。如果n/5(向上取整)是偶數,就找它的2個中位數中較大的乙個。以這個元素作為劃分基準。
例子:按遞增順序,找出下面29個元素的第18個元素:8,31,60,33,17,4,51,57,49,35,11,43,37,3,13,52,6,19,25,32,
54,16,5,41,7,23,22,46,29.
(1) 把前面25個元素分為5(=floor(29/5))組: (8,31,60,33,17),(4,51,57,49,35),(11,43,37,3,13),(52,6,19,25,32),(54,16,5,41,7);
(2) 提取每一組的中值元素,構成集合;
(3) 遞迴地使用演算法求取該集合的中值,得到m=25;
(4) 根據m=25, 把29個元素劃分為3個子陣列(按原有順序)
p=q=
r=(5) 由於|p|=13,|q|=1,k=18,所以放棄p,q,使k=18-13-1=4,對r遞迴地執行本演算法;
(6) 將r劃分成3(floor(15/5))組:,,
(7) 求取這3組元素的中值元素分別為:,這個集合的中值元素是43;
(8) 根據43將r劃分成3組: ,,
(9)將左半邊元素的個數與18作比較,若小於18,則對右邊進行遞迴,否則對左邊進行遞迴。
參考文章:
#includeusing namespace std;
templatevoid sort(t a, int m, int n) }}
templateint partition(t a, int l, int r,t midnum)
t df = a[l];
a[l] = a[point];
a[point] = df;
int i = l, j = r + 1;
t x = a[l];
while (true)
a[l] = a[j];
a[j] = x;
return j;
}templatet select(t a, int left, int right, int k)
for (int i = 0; i <= (right - left - 4) / 5; i++)
t x = select(a, left, left + (right - left - 4) / 5, (right - left - 4) / 10);
int local = partition(a, left, right, x), j = local - left + 1;
if (k <= j)
return select(a, left, local, k);
else
return select(a, local + 1, right, k - j); }
int main()
分治法 線性時間選擇(求第k小數)
給定線性序集中n個元素和乙個整數k,1 k n,要求找出這n個元素中第k小的元素,這裡給定的線性集是無序的 線性時間選擇隨機劃分法可以模仿隨機化快速排序演算法設計。基本思想是對輸入陣列進行遞迴劃分,與快速排序不同的是,它只對劃分出的子陣列之一進行遞迴處理。利用隨機函式產生劃分基準,將陣列a p r ...
線性時間選擇 第k個數
採用的演算法思想和快速排序十分相似,選取基準進行一次快排,得到乙個基準和左側小於基準右側大於基準的陣列。然後判斷基準的位置,如果第k個數在左邊便接著向左遞迴,如果在右側便接著向右側遞迴。include include include include include include includeus...
線性時間選擇問題(找第k大的數)
給定線性序集中n個元素和乙個整數k,n 2000000,1 k n,要求找出這n個元素中第k小的數。第一行有兩個正整數n,k.接下來是n個整數 0 ai 1e9 輸出第k小的數 6 31 3 5 2 4 6 定義陣列a存放資料,由於資料較多,用scanf進行輸入。陣列從0開始存入資料,所以第k大的數...