1. 程式人生 > 遊戲 >海關法拍一大批PS5和NS主機 以65.5萬人民幣拍出

海關法拍一大批PS5和NS主機 以65.5萬人民幣拍出

假設對以下10個數進行快速排序:

6 1 2 7 9 3 4 5 10 8
我們先模擬快速排序的過程:首先,在這個序列中隨便找一個數作為基準數,通常為了方便,以第一個數作為基準數。

6 1 2 7 9 3 4 5 10 8
在初始狀態下,數字6在序列的第1位。我們的目標是將6挪到序列中間的某個位置,假設這個位置是k kk。現在就需要尋找這個k kk,並且以第k位為分界點,左邊的數都≤ 6 \le6≤6,右邊的數都≥ 6 \ge6≥6。那麼如何找到這個位置k kk呢?

我們要知道,快速排序其實是氣泡排序的一種改進,氣泡排序每次對相鄰的兩個數進行比較,這顯然是一種比較浪費時間的。

而快速排序是分別從兩端開始”探測”的,先從右往左找一個小於6的數,再從左往右找一個大於6的數,然後交換他們。這裡可以用兩個變數i ii和j jj,分別指向序列最左邊和最右邊。我們為這兩個變數起個好聽的名字“哨兵i ii”和“哨兵j jj”。剛開始的時候讓哨兵i ii指向序列的最左邊,指向數字6。讓哨兵j jj指向序列的最右邊,指向數字8。

6 1 2 7 9 3 4 5 10 8
i j
首先哨兵j jj開始出動。因為此處設定的基準數是最左邊的數,所以需要讓哨兵j jj先出動,這一點非常重要。哨兵j jj一步一步地向左挪動(即j = j − 1 j = j-1j=j−1),直到找到一個小於6的數停下來。接下來哨兵i ii再一步一步向右挪動(即i = i + 1 i=i+1i=i+1),直到找到一個數大於6的數停下來。最後哨兵j jj停在了數字5面前,哨兵i ii停在了數字7面前。

6 1 2 7 9 3 4 5 10 8
i j
現在交換哨兵$i$和哨兵$j$所指向的元素的值。交換之後的序列如下。
6 1 2 5 9 3 4 7 10 8
i j
到此,第一次交換結束。接下來開始哨兵j jj繼續向左挪動(再友情提醒,每次必須是哨兵j先出發)。他發現了4 < 6 4<64<6,停下來。哨兵i ii也繼續向右挪動的,他發現了9 > 6 9>69>6,停下來。此時再次進行交換,交換之後的序列如下。

6 1 2 5 4 3 9 7 10 8
i j
第二次交換結束。哨兵j jj繼續向左挪動,他發現了3 < 6 3<63<6,又停下來。哨兵i ii繼續向右移動,此時哨兵i ii和哨兵j jj相遇了,哨兵i ii和哨兵j jj都走到3面前。說明此時“探測”結束。我們將基準數6和3進行交換。交換之後的序列如下。

3 1 2 5 4 6 9 7 10 8
i,j
到此第一輪“探測”真正結束。現在基準數6已經歸位,此時以基準數6為分界點,6左邊的數都小於等於6,6右邊的數都大於等於6。回顧一下剛才的過程,其實哨兵j jj的使命就是要找小於基準數的數,而哨兵i ii的使命就是要找大於基準數的數,直到i ii和j jj碰頭為止。

現在我們將第一輪“探測"結束後的序列,以6為分界點拆分成兩個序列,左邊的序列是“3 1 2 5 4”,右邊的序列是“9 7 10 8”。接下來還需要分別處理這兩個序列。因為6左邊和右邊的序列目前都還是很混亂的。不過不要緊,我們已經掌握了方法,接下來只要模擬剛才的方法分別處理6左邊和右邊的序列即可。現在先來處理6左邊的序列現吧。

3 1 2 5 4 6
重複第一輪的過程,應該得到如下序列:

2 1 3 5 4 6
OK,現在3已經歸位。接下來需要處理3左邊的序列:

2 1 3 6
處理之後,2已經歸位,序列“1”只有一個數,也不需要進行任何處理,因此“1”也歸位。

1 2 3 6
對於基數右邊的序列,採用和左邊相同的過程;最終將會得到這樣的序列,如下。

1 2 3 4 5 6 7 8 9 10

程式碼如下:

void Quick_Sort(int *arr, int begin, int end){
if(begin > end)
return;
int tmp = arr[begin];
int i = begin;
int j = end;
while(i != j){
while(arr[j] >= tmp && j > i)
j--;
while(arr[i] <= tmp && j > i)
i++;
if(j > i){
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
arr[begin] = arr[i];
arr[i] = tmp;
Quick_Sort(arr, begin, i-1);
Quick_Sort(arr, i+1, end);
}