將n個元素劃分成n/5組,每組5個元素,只可能有一組不是5個元素。再用氣泡排序法,將每組內的五個元素排好序,取出其中位數,共n/5個。
然後遞迴呼叫select方法找出這n/5個數中的中位數。若n/5是偶數,就找其最大的數。以這個元素作為劃分標準。判斷k與n的位置,再進行下一步的劃分。
以[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]為例查詢這29個元素中的第18個元素:
(1)把這29個元素分成6組:
(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)
(2)取出每一組的中位數,為31,49,13,25,16
(3)遞迴出的中值為25
(4)根據25將29個元素劃分為3個子陣列:
p =
q =
l =
(5)因為|p| = 13,|q| = 1,18>13 +1,所以第18個元素在l區域,找第18-13-1=4個元素,對l遞迴;
(6)將l劃分成3組:
(7)取出每一組的中位數,為51,43,41遞迴出的中值為43
(8)根據43將l組劃分為3個子陣列:
(9)因為第乙個子陣列中的元素的個數大於4,所以第18個元素在第乙個子陣列中,對第乙個子陣列遞迴;
(10)將第乙個子陣列分成了1組:
(11)取出中位數為33;
(12)根據33將第乙個子陣列分成3個子陣列:
(13)因為第乙個,第二個子陣列的元素的個數之和為4,所以33即為所求的第18個元素。
(一)**實現:
#include
#define size (29)
//主函式
int main (void);
//遞迴分組
int select(int
array,int left,int right,int ith);
//尋找中位數
int findmiddata(int
array,int left,int right);
//排序取中位數下標
int insertsort(int
array,int a,int b);
//分組,以中位數為界,將比中位數小的放在左邊,比中位數大的放在右邊
int partition(int
array,int left,int right,int mid);
//交換
void swap (int
array,int a,int b);
int main(void) ;
int size = size ;
int ith = 18 ;
for(int i = 0;i < size;i++)
printf("\n");
printf("該陣列的第%d位的元素是:%d\n",ith,select(array,0,size - 1,ith));
}//遞迴分組
int select(int
array,int left,int right,int ith)
if(partitionmid < ith - 1)else
}//尋找中位數
int findmiddata(int
array,int left,int right)
swap(array,i,mid);
}mid = insertsort(array,0,(right - left) / 5);
return mid;
}//排序取中位數下標
int insertsort(int
array,int a,int b)}}
//取中位數的下標
if((b - a + 1) % 2 == 0)else
}//分組,以中位數為界,將比中位數小的放在左邊,比中位數大的放在右邊
int partition(int
array,int left,int right,int mid)
while (array[j] > value)
if (i < j)
swap(array,i,j) ;
else
break ;
}for(int k = 0; k < size;k++)
}return mid;
}//交換
void swap (int
array,int a,int b)
(二)執行結果:
****
(1)時間複雜度
上述演算法中,設n = r - p + 1,即n為輸入陣列的長度,演算法的遞迴呼叫只有在n>=75時執行。因此,當n<75時,演算法select所用的計算時間不超過乙個常數,找到中位數的中位數x後,演算法select以x為劃分基準呼叫函式partition對陣列進行劃分,這需要o(n)時間。演算法select的迴圈共執行n/5次,每一次要o(1)時間,因此,共需o(n)時間。
設對n個元素的陣列呼叫select需要t(n)時間,那麼找中位數的中位數x至少要t(n/5)時間。先以證明,按照演算法所選的基準x進行劃分所得的兩個子陣列分別至多有3n/4個元素,所以無論對哪個子陣列呼叫select都至多用t
(3n/4)時間。
所以演算法的時間複雜度為
由此可得t(n)=o( n ).
(2)空間複雜度
演算法在歸併過程中,共需要n個輔助儲存空間來臨時儲存合併的結果。所以空間複雜度s(n)= o(n)
TopK問題 線性時間選擇
相信計算機專業的同學應該都對快速排序有或多或少的了解。設定此模組是因為,線性時間選擇topk與快速排序的思想有相通之處,可以輔助我們理解。快速排序的思路 設定乙個瞭望元素 劃分元素 以此元素為基礎,將工作區間 l,r 內的所有元素分割成兩部分。劃分元素以左均比其小,劃分元素以右均比其大。對分割元素左...
線性時間選擇
今天學習了線性時間選擇,主要是通過快排的方法,在乙個平均時間線性的情況下進行第k小元素的選擇,結合一道題目進行描述 題目來自演算法設計與分析就是王曉東的那本 output.txt 這題目分析一下可以得出就是尋找中位數 為什麼呢?將這些數字排列在數軸上尋找乙個到各個點距離最小的那個點,可以得知最中間的...
線性時間選擇
出自 http algorithm.chaoskey.com 02 07 題目 給定線性序集中n個元素和乙個整數k,1 k n,要求找出這n個元素中第k小的元素,這裡給定的線性集是無序的 具體解題 這裡我們將所有的數 n個 以每5個劃分為一組,共 n 5 組 將不足五個的那組忽略 然後用任意一種排序...