快速排序是對冒泡排序的改進,主要思想是通過一次排序將序列分成兩部分,左邊的部分全部小於基准值,右邊的部分大於基准值。在這一思想下,有不同的幾種實現方式。
(以下代碼中的測試數據來自用系統時間做種的隨機生成序列)
(除了以下版本,還有一些其他的快排的想法。)
1. 比較好理解的版本
1 /*
2 *2012年2月13日11:28:00
3 *quickSort
4 *這個版本是比較好理解的版本(效率不是最高的)
5 *quickSort函數第二個參數是要排序的數組起始下標,第三個參數是結束下標
6 *過程:
7 *1. 將最左邊的數設為val(也即關鍵字)
8 *2. 從i開始向右找比val大的數,找到后停下
9 *3. 從j開始向左找比val小的數,找到后停下
10 *4. 如果i>=j則離開循環
11 *5. 否則:交換當前的兩個數
12 *6. 對左邊遞歸
13 *7. 對右邊遞歸
14 */
15
16 #include <stdio.h>
17 #include <time.h>
18
19 #define MAX 10
20 #define SWAP(x, y) {int t=x; x=y; y=t;}
21
22 void quickSort(int *a, int left, int right);
23
24 int main(void)
25 {
26 int a[MAX] = {0};
27 int i;
28
29 srand(time(NULL));
30
31 printf("排序前:\n");
32 for (i=0; i<MAX; i++)
33 {
34 a[i] = rand()%100;
35 printf("%d ", a[i]);
36 }
37
38 quickSort(a, 0, MAX-1);
39
40 printf("\n排序后:\n");
41 for (i=0; i<MAX; i++)
42 {
43 printf("%d ", a[i]);
44 }
45 printf("\n");
46
47 return 0;
48 }
49
50 void quickSort(int *a, int left, int right)
51 {
52 if (left < right)
53 {
54 int i = left;
55 int j = right+1;
56
57 while (1)
58 {
59 while (i+1<MAX && a[++i]<a[left]);
60 while (j-1>-1 && a[--j]>a[left]);
61
62 if (i >= j)
63 {
64 break;
65 }
66 SWAP(a[i], a[j]);
67 }
68
69 SWAP(a[left], a[j]);
70
71 quickSort(a, left, j-1);
72 quickSort(a, j+1, right);
73 }
74 }
2. 對於上述方法進行改進,將基准值設定為序列中間的數,從中間向兩邊尋找
1 /*
2 *2012年2月13日16:26:31
3 *從中間向兩邊查找,具體過程類似於容易理解的版本
4 */
5
6 #include <stdio.h>
7 #include <time.h>
8
9 #define MAX 10
10 #define SWAP(x, y) {int t=x; x=y; y=t;}
11
12 void quickSort(int *a, int left, int right);
13
14 int main(void)
15 {
16 int a[MAX] = {0};
17 int i;
18
19 srand(time(NULL));
20
21 printf("排序前:\n");
22 for (i=0; i<MAX; i++)
23 {
24 a[i] = rand()%100;
25 printf("%d ", a[i]);
26 }
27
28 quickSort(a, 0, MAX-1);
29
30 printf("\n排序后:\n");
31 for (i=0; i<MAX; i++)
32 {
33 printf("%d ", a[i]);
34 }
35 printf("\n");
36
37 return 0;
38 }
39
40 void quickSort(int *a, int left, int right)
41 {
42 if (left < right)
43 {
44 int t = a[(left+right)/2];
45 int i = left - 1;
46 int j = right + 1;
47
48 while (1)
49 {
50 while (a[++i] < t);
51 while (a[--j] > t);
52
53 if (i >= j)
54 {
55 break;
56 }
57 SWAP(a[i], a[j]);
58
59 }
60
61 quickSort(a, left, i-1);
62 quickSort(a, j+1, right);
63 }
64 }
3. 再次改進算法。
有指針left和right,對於right,如果其所指的元素的值大於或者等於基准值,那么指針往左移一位,如果小於基准值,則和基准值交換;同理,對於left,如果left所指元素的值小於或者等於基准值,那么指針往右移一位,如果大於基准值,則和基准值交換。從right開始執行,重復這兩步驟,直至left == right為止。
對於基准的選取會影響算法的性能,這里取第一個元素為pivot。
1 /*
2 *2012年2月13日16:42:45
3 *效率較高的實現
4 */
5
6 #include <stdio.h>
7 #include <time.h>
8
9 #define MAX 10
10 #define SWAP(x, y) {int t=x; x=y; y=t;}
11
12 void quickSort(int *a, int left, int right);
13 int Partition(int *a, int left, int right);
14
15 int main(void)
16 {
17 int a[MAX] = {0};
18 int i;
19
20 srand(time(NULL));
21
22 printf("排序前:\n");
23 for (i=0; i<MAX; i++)
24 {
25 a[i] = rand()%100;
26 printf("%d ", a[i]);
27 }
28
29 quickSort(a, 0, MAX-1);
30
31 printf("\n排序后:\n");
32 for (i=0; i<MAX; i++)
33 {
34 printf("%d ", a[i]);
35 }
36 printf("\n");
37
38 return 0;
39 }
40
41 int Partition(int *a, int left, int right)
42 {
43 int pivot = a[left];
44 while (left < right)
45 {
46 while (left < right && a[right] >= pivot)
47 {
48 --right;
49 }
50 a[left] = a[right];
51 while (left < right && a[left] <= pivot)
52 {
53 ++left;
54 }
55 a[right] = a[left];
56 }
57
58 return left;
59 }
60
61 void quickSort(int *a, int left, int right)
62 {
63 int pivot;
64
65 if (left < right)
66 {
67 pivot = Partition(a, left, right);
68 quickSort(a, left, pivot-1);
69 quickSort(a, pivot+1, right);
70 }
71
72 }