快排是种十分巧妙而优秀的算法,时间复杂度为O(nlogn),花费了一点时间终于弄懂了其原理,写文以记录
步骤:
1.选择一个flag(通常用数组第一个元素)
2.将数组重新排列,使得左边均小于flag,右边均大于flag
3.对flag左右两侧递归1、2步骤
其中第2步为难点,如何实现?我们设一个j从右侧向左,一个i从左侧向右,停止条件为i和j相遇,当遇到小于flag的a[j],将a[j]与a[i]换位,当遇到大于flag的a[i],将a[i]与a[j]换位
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| #include<iostream>
int a[11] = { 5, 4, 8, 7, 3, 10, 6, -5, 9, -20, 7};
void swap(int* p, int* q) { int t = *p; *p = *q; *q = t; }
int quicksort(int left, int right) { if (left >= right) { return 0; }
int i = left; int j = right; int flag = a[i];
while (i < j) { while (i<j && a[j]>=flag) { j--; } swap(&a[i], &a[j]); while (i < j && a[i] <= flag) { i++; } swap(&a[i], &a[j]); }
quicksort(left, i - 1); quicksort(i + 1, right); }
int main() { printf("before: "); for (int i = 0; i < sizeof(a)/sizeof(int); i++) { printf("%d ", a[i]); }
quicksort(0, sizeof(a) / sizeof(int) - 1);
printf("\nafter: "); for (int i = 0; i < sizeof(a) / sizeof(int); i++) { printf("%d ", a[i]); } }
|
运行结果

上面的方法较易理解,使用swap进行交换,但实际程序这样写会占用更小的资源:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #include<iostream>
int a[11] = { 5, 4, 8, 7, 3, 10, 6, -5, 9, -20, 7};
int quicksort(int left, int right) { if (left >= right) { return 0; }
int i = left; int j = right; int flag = a[i];
while (i < j) { while (i < j && a[j] >= flag) { j--; } a[i] = a[j];
while (i < j && a[i] <= flag) { i++; } a[j] = a[i]; } a[i] = flag;
quicksort(left, i - 1); quicksort(i + 1, right); }
int main() { printf("before: "); for (int i = 0; i < sizeof(a)/sizeof(int); i++) { printf("%d ", a[i]); }
quicksort(0, sizeof(a) / sizeof(int) - 1);
printf("\nafter: "); for (int i = 0; i < sizeof(a) / sizeof(int); i++) { printf("%d ", a[i]); } }
|