第九章中位数と順序統計学の「第i小要素の最悪の状況を探す線形時間の選択最悪の運行時間はO(n)アルゴリズムである」
このアルゴリズムを用いてi番目の小要素を検索する最悪の動作時間はO(n)である.運行時間の証明はすごい!ああ、こんなにたくさんの証明を見て、私が発見したのは実は最も難しいのは数学の模型を提出して、数学の説明をして、この一歩を踏み出して、残りは集まったのです.
このアルゴリズムは9.2節の「所望運転時間こそO(n)」のRandomizedPartitionアルゴリズムよりも強く,最悪運転時間はO(n)である.なぜこんなにキックアスなのか、それは毎回区分するたびに最適な区分である「中分」を保証することができるからだ.中点を実現するには、まず中位数を見つけなければなりません.
アルゴリズムfind()プロセスは次のとおりです.
(1)まず元の配列aを5つのグループに分け,5つのグループ,,,そして各グループを挿入ソートし,各グループの中位数を得て配列bを構成する.この関数はSelect()です.
(2)b要素の個数が1でない場合、bに対してステップ1を実行し続ける.つまりSelect()再帰です.中位数xが見つかるまで.
(3)中位数xを一つのパラメータとしてPartition()関数に持ち込み,この関数はその分割関数をすばやく並べ替える変形である.分割後の中位数の下付きqを返します.
(4)qは配列aを2つの部分に分割し,i=q−p+1であればa[q]はi番目の小要素である.i
このアルゴリズムは9.2節の「所望運転時間こそO(n)」のRandomizedPartitionアルゴリズムよりも強く,最悪運転時間はO(n)である.なぜこんなにキックアスなのか、それは毎回区分するたびに最適な区分である「中分」を保証することができるからだ.中点を実現するには、まず中位数を見つけなければなりません.
アルゴリズムfind()プロセスは次のとおりです.
(1)まず元の配列aを5つのグループに分け,5つのグループ,,,そして各グループを挿入ソートし,各グループの中位数を得て配列bを構成する.この関数はSelect()です.
(2)b要素の個数が1でない場合、bに対してステップ1を実行し続ける.つまりSelect()再帰です.中位数xが見つかるまで.
(3)中位数xを一つのパラメータとしてPartition()関数に持ち込み,この関数はその分割関数をすばやく並べ替える変形である.分割後の中位数の下付きqを返します.
(4)qは配列aを2つの部分に分割し,i=q−p+1であればa[q]はi番目の小要素である.i
コードは次のとおりです.#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, x Select(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; }