[置頂]快速排序的遞迴方式和非遞迴方式
阿新 • • 發佈:2019-02-12
我們知道快遞排序大部分的版本都是遞迴的方式來實現的:通過Pritation來實現劃分,並遞迴實現前後的劃分。由於同學上次百度二面面試官問起快速排序的非遞迴的實現方式,當時同學不會,因為我們大部分看到的都是遞迴方式來實現快速排序。並沒有關注非遞迴的方式。但是仔細想想也是可以做的,因為遞迴的本質是棧,因此我們非遞迴實現的過程中,藉助棧來儲存中間變數就可以實現非遞迴了。在這裡中間變數也就是通過Pritation函式劃分之後分成左右兩部分的首尾指標,只需要儲存這兩部分的首尾指標即可。
遞迴的方式顯現如下:
首先貼出Pritation函式的實現,因為遞迴和非遞迴都需要用到該函式,該函式實現的版本有多種,這裡採用我比較熟悉的。
1 int Pritation(int* a, int left, int right) 2 { 3 if (a == NULL || left < 0 || right <= 0||left>=right) 4 return -1; 5 int priot = a[left]; 6 int i = left, j = right; 7 while (i < j) 8{ 9 while (i > j&&a[j] >= priot) 10 j--; 11 if(i<j) 12 a[i]=a[j]; 13 while (i < j&&a[i] <= priot) 14 i++; 15 if(i<j) 16 a[j]=a[i]; 17 } 18 a[i] = priot; 19 return i; 20 }
然後貼出遞迴的程式碼:(程式碼簡潔明瞭)
1 void QuickSort(int *a, int left,int right) 2 { 3 if (a == NULL || left < 0 || right <= 0 || left>right) 4 return; 5 int k = Pritation(a, i, j); 6 //下面是遞迴實現的程式碼 7 if (k > left) 8 QuickSort(a, left, k - 1); 9 if (k < right)10 QuickSort(a, k + 1, right); 11 }
最後貼出非遞迴的實現方式:
1 void QuickSort(int *a, int left,int right) 2 { 3 if (a == NULL || left < 0 || right <= 0 || left>right) 4 return; 5 stack<int>temp; 6 int i, j; 7 //(注意儲存順序)先將初始狀態的左右指標壓棧 8 temp.push(right);//先存右指標 9 temp.push(left);//再存左指標 10 while (!temp.empty()) 11 { 12 i = temp.top();//先彈出左指標 13 temp.pop(); 14 j = temp.top();//再彈出右指標 15 temp.pop(); 16 if (i < j) 17 { 18 int k = Pritation(a, i, j); 19 if (k > i) 20 { 21 temp.push(k - 1);//儲存中間變數 22 temp.push(i); //儲存中間變數 23 } 24 if (j > k) 25 { 26 temp.push(j); 27 temp.push(k + 1); 28 } 29 } 30 31 } 32 33 }
從上面的程式碼可以看出,儲存中間變數的時候需要注意儲存的順序,因為棧是後進先出的方式。