1. 程式人生 > >[置頂]快速排序的遞迴方式和非遞迴方式

[置頂]快速排序的遞迴方式和非遞迴方式

我們知道快遞排序大部分的版本都是遞迴的方式來實現的:通過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 }

從上面的程式碼可以看出,儲存中間變數的時候需要注意儲存的順序,因為棧是後進先出的方式。