舍伍德算法解决线性时间选择
一、需求分析
0.問(wèn)題描述
元素選擇問(wèn)題的一般提法是:給定線性序集中n個(gè)元素和一個(gè)整數(shù)k (1≤k≤n), 要求找出這n個(gè)元素中第k小的元素,即如果將這n個(gè)元素依其線性序排列時(shí),排在第k個(gè)位置的元素即為要找的元素。當(dāng)k=1時(shí),就是要找的最小元素:當(dāng)k=n時(shí), 就是要找最大元素;當(dāng)k=(n+1)/2 時(shí),稱為找中位數(shù)。
1.問(wèn)題分析
- 對(duì)于選擇問(wèn)題而言,用擬中位數(shù)作為劃分基準(zhǔn)可以保證在最壞的情況下用線性時(shí)間完成選擇。
- 如果只簡(jiǎn)單地用待劃分?jǐn)?shù)組的第一個(gè)元素作為劃分基準(zhǔn),則算法的平均性能較好,而在最壞的情況下需要O(n^2)計(jì)算時(shí)間。
- 舍伍德選擇算法則隨機(jī)地選擇一個(gè)數(shù)組元素作為劃分基準(zhǔn),這樣既保證算法的線性時(shí)間平均性能,又避免了計(jì)算擬中位數(shù)的麻煩。
3.輸出數(shù)據(jù)
分析并闡述要輸出的信息和數(shù)據(jù)(結(jié)果)
4.測(cè)試樣例設(shè)計(jì)
針對(duì)問(wèn)題的功能,設(shè)計(jì)5組有代表性的測(cè)試樣例,說(shuō)明每組測(cè)試樣例的測(cè)試目的
二、算法設(shè)計(jì)與分析
1.算法的基本思想
類似于快排的一種思想。
- 隨機(jī)選擇一個(gè)基準(zhǔn)值pivot,將基準(zhǔn)值與范圍左側(cè)元素交換位置。
- 以基準(zhǔn)值為軸進(jìn)行劃分,先從右往左找到一個(gè)位置j的元素小于pivot,然后從左往右找到一個(gè)位置i的元素大于pivot,交換兩個(gè)元素的位置。
- 當(dāng)i==j時(shí)停止交換,這時(shí)j的左側(cè)元素小于等于pivot,右側(cè)元素大于等于pivot、
- 因?yàn)閖處的元素肯定小于等于pivot,將L與j處元素交換位置,j位置的元素就是這個(gè)序列里面第 j - L+1小的元素。
- 如果j?- L +1==k,則問(wèn)題解決
- 否則判斷k與j?- L +1的相對(duì)大小,當(dāng)j?- L +1< k時(shí)繼續(xù)對(duì)右側(cè)的序列重復(fù)以上過(guò)程,否則對(duì)左側(cè)序列重復(fù)以上過(guò)程,直到找到滿足條件的j?- L +1
2.輸入和輸出的格式
- 從文件輸入,輸出到文件。
- 輸入第一行是元素個(gè)數(shù)n和要求的元素的位置k
- 第二行是n個(gè)元素的值
3.算法的具體步驟
4.算法的時(shí)空分析
①時(shí)間復(fù)雜度:
-
①時(shí)間復(fù)雜度:
劃分基準(zhǔn)是隨機(jī)的。可以證明,當(dāng)用算法Select對(duì)含有n個(gè)元素的數(shù)組進(jìn)行劃分時(shí),劃分出的低區(qū)子數(shù)組中含有一個(gè)元素的概率為2/n,含有i個(gè)元素的概率為1/n (i=2, 3,.,. n-1)。
設(shè)T(n)是算法Select作用于一個(gè)含有n個(gè)元素的輸入數(shù)組上所需的期望時(shí)間的上界,且T(n)是單調(diào)遞增的。在最壞情況下,第k小元素總是被劃分在較大的子數(shù)組中。得到關(guān)于T(n)的遞歸式
? ? ? ? ?
-
解遞歸式得到結(jié)果:O(n)
②空間復(fù)雜度:
存儲(chǔ)元素的值,O(n)
②空間復(fù)雜度:
存儲(chǔ)元素的值,O(n)
三、測(cè)試結(jié)果
?
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");//內(nèi)聯(lián)交換函數(shù) 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];} //隨機(jī)選擇劃分基準(zhǔn)int i = l, j = l + rand() % (r - l + 1);Swap(a[i], a[j]);j = r + 1;Type pivot = a[l];//以劃分基準(zhǔn)為軸做元素交換while (true){while (i<r&&a[++i] < pivot);while (j>l&&a[--j] > pivot);if (i >= j){break;}Swap(a[i], a[j]);}//如果最后基準(zhǔn)元素在第k個(gè)元素的位置,則找到了第k小的元素 if (j - l + 1 == k){return pivot;} //a[j]必然小于pivot,做最后一次交換,滿足左側(cè)比pivot小,右側(cè)比pivot大a[l] = a[j];a[j] = pivot; //對(duì)子數(shù)組重復(fù)劃分過(guò)程if (j - l + 1 < k){k = k - (j - l + 1 );//基準(zhǔn)元素右側(cè),求出相對(duì)位置 l = j + 1;}else{//基準(zhǔn)元素左側(cè) 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; }?
總結(jié)
以上是生活随笔為你收集整理的舍伍德算法解决线性时间选择的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: [html] DOM和BOM有什么区别
- 下一篇: tomcat设置编码