【題目】:給定線性序集中n個元素和乙個整數k,1≤k≤n,要求找出這n個元素中第k小的元素,(這裡給定的線性集是無序的)
【具體解題】:這裡我們將所有的數(n個),以每5個劃分為一組,共[n/5]組(將不足五個的那組忽略);然後用任意一種排序演算法(因為只對五個數進行排序,所以任取一種排序法就可以了,這裡我選用氣泡排序
),將每組中的元素排好序再分別取每組的中位數,得到[n/5]個中位數;再取這[n/5]個中位數的中位數(如果n/5是偶數,就找它的2個中位數中較大的乙個)作為劃分基準,將全部的數劃分為兩個部分,小於基準的在左邊,大於等於基準的放右邊。
在這種情況下,找出的基準x至少比3(n-5)/10個元素大,因為在每一組中有2個元素小於本組的中位數,中位數處於1/2*[n/5-1],即n/5個中位數中又有(n-5)/10個小於基準x。同理,基準x也至少比3(n-5)/10個元素小。而當n≥75時,3(n-5)/10≥n/4所以按此基準劃分所得的2個子陣列的長度都至少縮短1/4。
程式**如下:
#include這個題目關鍵在尋找劃分基準,從而提高尋找效率,時間複雜度為o(n);#include
#include
#define max_value 10000
#define random() rand()%max_value
#define n 10000
int a[n];
class find
}int partition(int p,int r,int x) //陣列a
中從a[p]
到a[r]
的元素按照x劃分
,大於x的在左邊,小於
x的在右邊
}}return i-1;
}int select(int p,int r,int k) //
尋找中位數
for(int i=0;i<(r-p-4)/5;i++)
int x=select(p,p+(r-p-4)/5,(r-p+6)/10);
i=partition(p,r,x);
int j=i-p+1;
if(k<=j)
return select(p,i,k);
else
return select(i+1,r,k-j);}};
void main()
cout<
start=clock();
find f;
int n=5000;
cout<<"the no."<
end=clock();
elapsed=((double)(end-start));///clocks_per_sec;
cout<<"time: "<
}
本文固定鏈結為:http://www.hinn.cn/2008/04/randomizedselect.html
最壞情況為線性時間的選擇演算法
輸入 一系列數a 0 a n 1 和乙個整數k 輸出 這列數中第k小的數 同樣的問題在上篇文章中用快速排序模型,我們得到的平均時間複雜度是o n 但是遺憾的是最壞情況會達到o n 2 這篇文章中我們還是使用快速排序的模型,但是改變了劃分的方式,這個演算法會保準得到乙個很好的劃分。將該演算法叫做sel...
最壞情況為線性時間的選擇演算法
題目 在n個元素的無序陣列中選擇第k 1 k n 小元素。當k 1時,相當於找最小值。當k n時,相當於找最大值。當k n 2時,稱中值。要求 線性時間內完成,即o n 演算法解析 通過執行下列步驟,演算法select可以確定乙個有n 1個不同元素的輸入陣列中第i小的元素。如果n 1,則select...
演算法導論,9 3,最壞情線性時間的選擇演算法
演算法的思想是很妙的,發現實現起來有點困難,然後發現網上貌似完整的 沒找見,就自己盡力寫了乙個。寫完測試了一下,總數組是1乙個數,然後在查詢第i小的數,當i小的時候,隨機線性查詢完爆最壞情況為線性時間的演算法,當i變得很大,執行時間會相對接近。還有就是陣列下標0開始的特性,感覺會造成很大的不方便,直...