給定線性序集中n個元素和乙個整數k,1≤k≤n,要求找出這n個元素中第k小的元素,(這裡給定的線性集是無序的)。
線性時間選擇隨機劃分法可以模仿隨機化快速排序演算法設計。基本思想是對輸入陣列進行遞迴劃分,與快速排序不同的是,它只對劃分出的子陣列之一進行遞迴處理。
利用隨機函式產生劃分基準,將陣列a[p:r]劃分成兩個子陣列a[p:i]和a[i+1:r],使a[p:i]中的每個元素都不大於a[i+1:r]中的每個元素。接著"j=i-p+1"計算a[p:i]中元素個數j.如果kj,則第k小元素在子陣列a[i+1:r]中。注意:由於已知道子陣列a[p:i]中的元素均小於要找的第k小元素,因此,要找的a[p:r]中第k小元素是a[i+1:r]中第k-j小元素。 在最壞的情況下,例如:總是找到最小元素時,總是在最大元素處劃分,這是時間複雜度為o(n^2)。但平均時間複雜度與n呈線性關係,為o(n) 。
type randomizedselect(type a,int p,int r,int k)
中位數:是指將資料按大小順序排列起來,形成乙個數列,居於數列中間位置的那個資料。
例子:•按遞增順序,找出下面
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)
因為k=4
,第乙個子陣列的元素個數大於
k,所以放棄後面兩個子陣列,以
k=4對第乙個子陣列遞迴呼叫本演算法;
•(10)
將這個子陣列分成
5個元素的一組:
,取其中值元素為33;
•(11)
根據33
,把第乙個子陣列劃分成
,,;
•(12)
因為k=4,
而第一、第二個子陣列的元素個數為
4,所以
33即為所求取的第
18個小元素。
type select(type a, int p, int r, int k)
; for ( int i = 0; i<=(r-p-4)/5; i++ )
將a[p+5*i]至a[p+5*i+4]的第3小元素
與a[p+i]交換位置;
//找中位數的中位數,r-p-4即上面所說的n-5
type x = select(a, p, p+(r-p-4)/5, (r-p-4)/10);
int i=partition(a,p,r, x),
j=i-p+1;
if (k<=j) return select(a,p,i,k);
else return select(a,i+1,r,k-j);
}
實現步驟:
演算法思路:
分治法 線性時間選擇
演算法思想 利用快速排序的方法將a p r 被劃分成兩個子陣列a p i 和a i 1 r 使a p i 中的每個元素都不大於a i 1 r 中每個元素。接著演算法計算子陣列a p i 中元素個數j。如果k j,則第k小的數落在左區間,否則落在右區間,直到k j時,找到第k小的數。對於有重複數字的無...
分治法 線性時間選擇
問題 給定線性序集中n個元素和乙個整數k,1 k n,要求找出這n個元素中第k小的元素,演算法的複雜度為o n 思路分析 首先,假如我們要找最大或者最小的元素,那麼只需遍歷一遍序列即可,複雜度為o n 假如要找第k大的元素,k n logn或者k n nlogn時,利用堆排序,時間複雜度仍然可以達到...
線性選擇 求n個數中第k小數
include include include template int partition type a,int p,int r a p a j a j x return j template int randamizedpartition type a,int p,int r template ...