第九章中位元和順序統計學 之 “尋找第i小元素之最壞情況線性時間的選擇 最壞已耗用時間就為O(n)演算法”

來源:互聯網
上載者:User

使用這個演算法尋找第i小元素的最壞情況已耗用時間為O(n)。關於已耗用時間的證明簡直屌爆了!唉,看了這麼多證明,我發現其實最難的就是提出數學模型、數學描述,邁出這一步,剩下的就是湊了。

這個演算法比9.2節中那個“期望已耗用時間才是O(n)”的RandomizedPartition演算法更加牛逼,它最壞已耗用時間就是O(n)。之所以這麼屌,是因為它每次劃分都能保證是最佳劃分,即“中分”。要想實現中分,就得先把中位元找出來。

演算法find()過程如下:

(1)先把原數組a劃分成五個一組,五個一組、、、,然後對每個小組進行插入排序,得到每個小組的中位元,組成數組b。這個函數為Select()。

(2)若b元素個數不為1,則繼續對b運行步驟一。即Select()遞迴。直到找到中位元x。

(3)把中位元x作為一個參數,帶入Partition()函數,這個函數是快速排序那個劃分函數的變形。返回劃分後中位元所在的下標q。

(4)q把數組a劃分成兩部分,如果i=q-p+1,則a[q]即為第i小元素。若i<q-p+1,則i應該在低區,在低區進行遞迴find()。否則,i在高區,對高區進行遞迴find()。

代碼如下:

#include <iostream>#include <string.h>using namespace std;//對每個小組進行插入排序 void InsertionSort(int *a,int p,int r,int &mid){int i;for(int j=p+1;j<=r;j++){        i=j-1;int key=a[j];while(i>=p && a[i]>key){a[i+1]=a[i];i--;}a[i+1]=key;}int d=r-p+1;if(d%2==0){d=d/2-1;}else{d=d/2;}//cout<<d;mid=a[d+p];}//尋找數組a的中位元,放到x中void Select(int *a,int p,int r,int &x){if(p==r){x=a[p];return;}int n=r-p+1;int m=0;if(n%5==0){m=n/5;}else{m=n/5+1;}//將數組劃分為五個一組五個一組...,每一組進行插入排序,並在排序後取出每一組的中位元,放入數組b中    int b[m];int i=p;for(int j=0;j<m;j++){int mid;if(i+4<=r){InsertionSort(a,i,i+4,mid);b[j]=mid;i+=5;}else{InsertionSort(a,i,r,mid);b[j]=mid;}//cout<<"i="<<i<<" mid="<<mid<<" j="<<j<<" m="<<m<<" r="<<r;system("pause");}//對包含各分組中位元的數組b,遞迴調用Select,找出中位元xSelect(b,0,m-1,x);}//根據中位元x,對數組a進行劃分 int Partition(int *a,int p,int r,int x){int index=-1;for(int i=p;i<=r;i++){if(a[i]==x){index=i;//cout<<i;system("pause");break;}}if(index==-1){    cout<<"error"<<endl;exit(1);}int temp=a[index];a[index]=a[r];a[r]=temp;int i=p-1;for(int j=p;j<r;j++){if(a[j]<=x){i++;int tmp=a[i];a[i]=a[j];a[j]=tmp;}}int pivot=a[r];a[r]=a[i+1];a[i+1]=pivot;return i+1;}//尋找第i小的數void find(int *a,int p,int r,int i,int &result){int x;Select(a,p,r,x);//以x為主元,對數組a進行劃分int q=Partition(a,p,r,x);int k=q-p+1;if(k==i){result=a[q];}else if(k>i){find(a,p,q-1,i,result);}else{find(a,q+1,r,i-k,result);}}void Output(int *a,int n){     for(int i=0;i<n;i++)     {         printf("%d ",a[i]);     }     cout<<endl;}int main(){    int n=11;    int a[n];    srand((unsigned int)time(NULL));    for(int i=0;i<n;i++)    {         a[i]=rand()%n;    }    Output(a,n);int result=-1;int i;while(1){    cout<<"輸入你要尋找的第i小:i=";     cin>>i;        find(a,0,n-1,i,result);    cout<<"i="<<i<<" result="<<result<<endl;     }    //Output(a,n);    system("pause");    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.