問題描述:ios
給定線性序集中n個元素和一個整數k,1≤k≤n,要求找出這n個元素中第k小的元素,即若是將這n個元素依其線性序排列時,排在第k個的元素即爲要找到元素。算法
細節須知:(與以前的隨筆相比)windows
(1)設置了對於程序運行次數的手動輸入設定數組
(2)取消了文件的讀入,直接生成隨機數進行排序查找ui
(3)擴大了隨機數的範圍、數組的可申請大小spa
(4)時間統計精確到了微秒級設計
(5)運行結束後一次性寫入提高了程序穩定性,寫入的數據可用於數據分析圖表code
算法原理:orm
將n個輸入元素劃分紅⌈n/5⌉個組,每組5個元素,只可能有一個組不是5個元素。用任意一種排序算法,將每組中的元素排好序,並取出每組的中位數,共⌈n/5⌉個。遞歸調用算法Select來找出⌈n/5⌉個元素的中位數。若是⌈n/5⌉是偶數,就找它的兩個中位數中較大的一個。以這個元素做爲劃分基準。以此遞歸排序找到所需的第k項。blog
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<fstream> 6 #include<algorithm> 7 #include<windows.h> 8 #include<ctime> 9 using namespace std; 10 LARGE_INTEGER nFreq;//LARGE_INTEGER在64位系統中是LONGLONG,在32位系統中是高低兩個32位的LONG,在windows.h中經過預編譯宏做定義 11 LARGE_INTEGER nBeginTime;//記錄開始時的計數器的值 12 LARGE_INTEGER nEndTime;//記錄中止時的計數器的值 13 14 //一次快排 15 int Partition(int nums[],int p,int r,int x) 16 { 17 if(p>r) return -1; 18 //找出基準x的位置並與第一位交換 19 for(int i=p;i<=r;i++) 20 { 21 if(nums[i]==x) 22 { 23 swap(x,nums[p]); 24 break; 25 } 26 } 27 int left=p,right=r; 28 while(left<right) 29 { 30 while(left<right && nums[right]>=x) right--; 31 nums[left]=nums[right]; 32 while(left<right && nums[left]<x) left++; 33 nums[right]=nums[left]; 34 } 35 nums[left]=x; 36 return left; 37 } 38 39 //快速排序 40 void QuickSort(int nums[],int low,int high) 41 { 42 if(low>high) return; 43 int key=nums[low]; 44 int left=low,right=high; 45 while(left<right) 46 { 47 while(left<right && nums[right]>=key) right--; 48 nums[left]=nums[right]; 49 while(left<right && nums[left]<key) left++; 50 nums[right]=nums[left]; 51 } 52 nums[left]=key; 53 QuickSort(nums,low,left-1); 54 QuickSort(nums,left+1,high); 55 } 56 57 int Select(int nums[],int p,int r,int k) 58 { 59 if(r-p<75) 60 { 61 QuickSort(nums,p,r); 62 return nums[p+k-1]; 63 } 64 //每5個爲一組,找到各組的中位數,並存儲在前(r-p-4)/5個位置裏 65 for(int i=0;i<=(r-p-4)/5;i++) 66 { 67 QuickSort(nums,p+5*i,p+5*i+4); 68 swap(nums[p+i],nums[p+5*i+2]); 69 } 70 //找全部中位數的中位數 71 int x=Select(nums,p,p+(r-p-4)/5,(r-p-4)/10); 72 //以x爲基準作一次快排 73 int i=Partition(nums,p,r,x); 74 int j=i-p+1; 75 //判斷k屬於那個部分 76 if(k<=j) 77 return Select(nums,p,i,k); 78 else 79 return Select(nums,i+1,r,k-j); 80 } 81 int main(){ 82 ofstream fout; 83 double cost; 84 int i = 0,m = 0,n = 0,key = 0; 85 cout<<"Please enter the number of times you want to run the program:"; //輸入程序運行次數 86 cin>>m; 87 int data_amount[m]; 88 double runtime[m]; 89 srand((unsigned int)time(NULL)); //設置隨機數種子 90 for(i=0;i<m;i++) 91 { 92 n=10000+RAND_MAX*(rand()%300)+rand(); //RAND_MAX=32767,隨機生成數據量 93 data_amount[i]=n; //限定數據規模爲10000~9872867 94 cout<<"☆The "<<i+1<<"th test Data amount is:"<<n<<endl; 95 int j=0; 96 int *a=(int *)malloc(n*sizeof(int)); 97 for(j=0;j<n;j++){ 98 a[j]=RAND_MAX*(rand()%400)+rand(); //隨機生成0~13139567的隨機數 99 } 100 key=rand()%10000+1; //隨機生成1~10000做爲所要選擇的次序 101 QueryPerformanceFrequency(&nFreq);//獲取系統時鐘頻率 102 QueryPerformanceCounter(&nBeginTime);//獲取開始時刻計數值 103 int t=Select(a,0,n-1,key); 104 QueryPerformanceCounter(&nEndTime);//獲取中止時刻計數值 105 cost=(double)(nEndTime.QuadPart - nBeginTime.QuadPart) / (double)nFreq.QuadPart; 106 runtime[i]=cost; 107 cout<<"The "<<key<<"th number is:"<<t<<endl; 108 cout<<"The running time is:"<<cost<<" s"<<endl; 109 free(a); 110 } 111 fout.open("data.txt"); 112 if(!fout){ 113 cerr<<"Can not open file 'data.txt' "<<endl; 114 return -1; 115 } 116 for(i=0;i<m;i++){ 117 fout<<data_amount[i]<<","<<runtime[i]<<endl; 118 } 119 fout.close(); 120 cout<<"Success!"<<endl; 121 return 0; 122 }
程序設計思路:
假設輸入的數據規模爲n,要查找的數據次序爲k。
(1)判斷數組長度,若小於75則直接進行快速排序,不然進行以後的算法。
(2)將n個輸入元素劃分紅⌈n/5⌉個組,每組五個元素。用快速排序將每組中的元素排好序,並肯定每組的中位數,共⌈n/5⌉個。
(3)遞歸調用算法Select來找出這⌈n/5⌉個元素的中位數。若是⌈n/5⌉是偶數,就找它的兩個中位數中較大的一個。以這個元素做爲劃分基準。
(4)以此遞歸調用進行排序,最終搜索獲得要找的第k項。
時間複雜性分析:
爲了分析算法Select的計算時間複雜性,設n=r-p+1,即n爲輸入數組的長度。算法的遞歸調用只有在n≥75時才執行。所以,當n<75是算法Select所用的計算時間不超過一個常數C1。找到中位數的中位數x後,算法Select以x爲劃分基準調用Partition對數組a[p:r]進行劃分,這須要O(n)時間。算法Select的for循環體行共執行n/5次,每一次須要O(1)時間。所以,執行for循環共需O(n)時間。
設對n個元素的數組調用算法Select須要T(n)時間,那麼找中位數的中位數x至多用了T(n/5)的時間。已經證實了,按照算法所選的基準x進行劃分所獲得的2個子數組分別至多有3n/4個元素。因此,不管對哪個子數組調用,Select都至多用了T(3n/4)的時間。
總之,能夠獲得關於T(n)的遞歸式
解此遞歸式可得T(n)=O(n)。
通過5000次不一樣規模數據的實驗並統計運行時間獲得以下算法效率分析圖: