快速排序遞迴思想 n個元素中第m小的元素
阿新 • • 發佈:2019-01-05
利用快速排序的思想,編寫一個遞迴演算法,求出給定的n個元素中第m個最小的元素
思路:取陣列第m個元素也就是a[m-1]作為每一次迴圈的一個閾值,將大於a[m-1]的全部放在陣列的右邊,小於a[m-1]的全部放在陣列的左邊,如果一直這樣迴圈下去,那麼最後a[m-1]這個單元中存放的就一定是第m小的資料。
程式碼分析:至於程式中比較難理解的我覺得是:
if(j < m-1) left = i; //這一句的意思是,程式是想尋找第m小的資料,但是j<m-1,表示現在這個閾值比第m個最小的數還小,然而存放在陣列中,比當前閾值大的數的集合中的第一個數的下標正好是i,因為i是從while(privot < a[i]) i++; 這個語句中跳出來的,所以這個時候將左查詢範圍設定為i。
if(i > m-1) right = j; 跟上面的理解差不多。
注意:其實這兩個if判斷來修正left和right查詢範圍的語句完全可以不需要,因為不修改的話每次都是從最左端查詢到最右端,結果是一定能夠查找出來的,只是效率方面可能就沒有加上這兩句好了。
PS:本文借鑑了https://blog.csdn.net/laoniu_c/article/details/38127967的思路,根據題意進行程式設計,程式碼如下:
#include <iostream> using namespace std; int findm_min(int *a, int n, int m, int left, int right) { int piv = a[m-1]; //取闕值 int i = left, j = right; if(i < j) { //將右端比闕值小的數和左端比闕值大的數交換位置 while(piv < a[j]) j--; while(piv > a[i]) i++; if(i < j) { //通過位運算交換兩個數的位置 a[i] = a[i] ^ a[j]; a[j] = a[i] ^ a[j]; a[i] = a[i] ^ a[j]; i++, j--; } if(i == j && a[i] == piv) return piv; //符合預想條件,返回最後結果 } else return a[m-1]; //優化演算法 if(j < m - 1) left = i; if(i > m - 1) right = j; //遞迴 findm_min(a, n, m, left, right); } int main() { int n, m; //輸入n,m cout << "請輸入n和m:" << endl; cin >> n >> m; //輸入陣列元素 int *a = new int[n]; cout << "請輸入n個數:" << endl; for(int i = 0; i < n; i++) cin >> a[i]; //計算並輸出最後結果 cout << n << "個數中第" << m << "小的數為:" << endl; cout << findm_min(a, n, m, 0, n - 1) << endl; return 0; }