快速排序的分析及c語言程式碼
快速排序(Quicksort)是對氣泡排序的一種改進。它的基本思想是:通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分別進行快速排序,整個排序過程可以遞迴進行,以此達到整個資料變成有序序列。
設要排序的陣列是A[0]……A[N-1],首先任意選取一個數據(通常選用陣列的第一個數)作為關鍵資料,然後將所有比它小的數都放到它前面,所有比它大的數都放到它後面,這個過程稱為一趟快速排序。值得注意的是,快速排序不是一種穩定的排序演算法,也就是說,多個相同的值的相對位置也許會在演算法結束時產生變動。
一趟快速排序的演算法是:
1)設定兩個變數i、j,排序開始的時候:i=0,j=N-1;
2)以第一個陣列元素作為關鍵資料,賦值給key,即key=A[0];
3)從j開始向前搜尋,即由後開始向前搜尋(j--),找到第一個小於key的值A[j],將A[j]和A[i]互換;
4)從i開始向後搜尋,即由前開始向後搜尋(i++),找到第一個大於key的A[i],將A[i]和A[j]互換;
5)重複第3、4步,直到i=j;(3,4步中,沒找到符合條件的值,即3中A[j]不小於key,4中A[i]不大於key的時候改變j、i的值,使得j=j-1,i=i+1,直至找到為止。找到符合條件的值,進行交換的時候i, j指標位置不變。另外,i==j
示例
假設使用者輸入瞭如下陣列:
下標012 34 5
資料627 38 9
建立變數i=0(指向第一個資料), j=5(指向最後一個數據), k=6(賦值為第一個資料的值)。
我們要把所有比k小的數移動到k的左面,所以我們可以開始尋找比6小的數,從j開始,從右往左找,不斷遞減變數j的值,我們找到第一個下標3的資料比6小,於是把資料3移到下標0的位置,把下標0的資料6移到下標3,完成第一次比較:
下標012 34 5
資料327 68 9
i=0 j=3 k=6
接著,開始第二次比較,這次要變成找比k大的了,而且要從前往後找了。遞加變數i
下標012 34 5
資料326 78 9
i=2 j=3 k=6
稱上面兩次比較為一個迴圈。
接著,再遞減變數j,不斷重複進行上面的迴圈比較。
在本例中,我們進行一次迴圈,就發現i和j“碰頭”了:他們都指向了下標2。於是,第一遍比較結束。得到結果如下,凡是k(=6)左邊的數都比它小,凡是k右邊的數都比它大:
下標012 34 5
資料326 78 9
如果i和j沒有碰頭的話,就遞加i找大的,還沒有,就再遞減j找小的,如此反覆,不斷迴圈。注意判斷和尋找是同時進行的。
然後,對k兩邊的資料,再分組分別進行上述的過程,直到不能再分組為止。
注意:第一遍快速排序不會直接得到最終結果,只會把比k大和比k小的數分到k的兩邊。為了得到最後結果,需要再次對下標2兩邊的陣列分別執行此步驟,然後再分解陣列,直到陣列不能再分解為止(只有一個數據),才能得到正確結果。
C語言程式碼如下:
#include <stdio.h>
void Q_sort(int a[],int num);
static int m=0,n=0;
int main() {
int k = 0;
int a[9] = {3,6,5,9,7,1,8,2,4};
printf("原陣列:");
for (k=0; k<9; k++) {
printf("%d,",a[k]);
}
printf("\n");
Q_sort(a, 9);
printf("排序後的陣列:");
for (k=0; k<9; k++) {
printf("%d,",a[k]);
}
printf("\n比較次數為%d\n 交換次數為:%d\n",m,n);
return 0;
}
void Q_sort(int a[],int num){
int i = 0;
int j = num - 1;
int k = a[0];
if (num>1) {//重複的判斷條件,如果長度小於2,則不需排序
while (i != j) {
for (; i<j; j--) {
m++;
if (a[j]<k) {
a[i] = a[j];
n++;
break;
}
}
for (; i<j; i++) {
m++;
if (a[i]>k) {
a[j] = a[i];
n++;
break;
}
}
a[i] = k;
}
Q_sort(a, i);
Q_sort(a+i+1, num-i-1);
}
}
用mac終端執行效果如下: