舍伍德算法解决线性时间选择
一、需求分析
0.問題描述
元素選擇問題的一般提法是:給定線性序集中n個元素和一個整數k (1≤k≤n), 要求找出這n個元素中第k小的元素,即如果將這n個元素依其線性序排列時,排在第k個位置的元素即為要找的元素。當k=1時,就是要找的最小元素:當k=n時, 就是要找最大元素;當k=(n+1)/2 時,稱為找中位數。
1.問題分析
- 對于選擇問題而言,用擬中位數作為劃分基準可以保證在最壞的情況下用線性時間完成選擇。
- 如果只簡單地用待劃分數組的第一個元素作為劃分基準,則算法的平均性能較好,而在最壞的情況下需要O(n^2)計算時間。
- 舍伍德選擇算法則隨機地選擇一個數組元素作為劃分基準,這樣既保證算法的線性時間平均性能,又避免了計算擬中位數的麻煩。
3.輸出數據
分析并闡述要輸出的信息和數據(結果)
4.測試樣例設計
針對問題的功能,設計5組有代表性的測試樣例,說明每組測試樣例的測試目的
二、算法設計與分析
1.算法的基本思想
類似于快排的一種思想。
- 隨機選擇一個基準值pivot,將基準值與范圍左側元素交換位置。
- 以基準值為軸進行劃分,先從右往左找到一個位置j的元素小于pivot,然后從左往右找到一個位置i的元素大于pivot,交換兩個元素的位置。
- 當i==j時停止交換,這時j的左側元素小于等于pivot,右側元素大于等于pivot、
- 因為j處的元素肯定小于等于pivot,將L與j處元素交換位置,j位置的元素就是這個序列里面第 j - L+1小的元素。
- 如果j?- L +1==k,則問題解決
- 否則判斷k與j?- L +1的相對大小,當j?- L +1< k時繼續對右側的序列重復以上過程,否則對左側序列重復以上過程,直到找到滿足條件的j?- L +1
2.輸入和輸出的格式
- 從文件輸入,輸出到文件。
- 輸入第一行是元素個數n和要求的元素的位置k
- 第二行是n個元素的值
3.算法的具體步驟
4.算法的時空分析
①時間復雜度:
-
①時間復雜度:
劃分基準是隨機的。可以證明,當用算法Select對含有n個元素的數組進行劃分時,劃分出的低區子數組中含有一個元素的概率為2/n,含有i個元素的概率為1/n (i=2, 3,.,. n-1)。
設T(n)是算法Select作用于一個含有n個元素的輸入數組上所需的期望時間的上界,且T(n)是單調遞增的。在最壞情況下,第k小元素總是被劃分在較大的子數組中。得到關于T(n)的遞歸式
? ? ? ? ?
-
解遞歸式得到結果:O(n)
②空間復雜度:
存儲元素的值,O(n)
②空間復雜度:
存儲元素的值,O(n)
三、測試結果
?
5 2
5 9 1 4 6
10 8
19 2 56 1 ?3 5 3 2 7 9?
全部代碼:
#include <iostream> #include <time.h> #include <stdlib.h> #include <fstream> using namespace std; ifstream in("input.txt"); ofstream out("output.txt");//內聯交換函數 template <class Type> inline void Swap(Type& a, Type& b){Type temp = a;a = b;b = temp; }template<class Type> Type select(Type a[], int l, int r, int k){while (true){if (l >= r){return a[l];} //隨機選擇劃分基準int i = l, j = l + rand() % (r - l + 1);Swap(a[i], a[j]);j = r + 1;Type pivot = a[l];//以劃分基準為軸做元素交換while (true){while (i<r&&a[++i] < pivot);while (j>l&&a[--j] > pivot);if (i >= j){break;}Swap(a[i], a[j]);}//如果最后基準元素在第k個元素的位置,則找到了第k小的元素 if (j - l + 1 == k){return pivot;} //a[j]必然小于pivot,做最后一次交換,滿足左側比pivot小,右側比pivot大a[l] = a[j];a[j] = pivot; //對子數組重復劃分過程if (j - l + 1 < k){k = k - (j - l + 1 );//基準元素右側,求出相對位置 l = j + 1;}else{//基準元素左側 r = j - 1;}} }template <class Type> Type Select(Type a[],int n,int k){if(k<1||k>n){printf("Index out of bounds\n");exit(0);}return select(a,0,n-1,k); }int main(){int n,k,r;while(in>>n){in>>k;int a[n];for(int i=0;i<n;i++)in>>a[i];r=Select<int> (a,n,k);out<<r<<'\n';}in.close();out.close();return 0; }?
總結
以上是生活随笔為你收集整理的舍伍德算法解决线性时间选择的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [html] DOM和BOM有什么区别
- 下一篇: tomcat设置编码