基本思想:
首先选择一个基点base, 凡是比 base 大的都放在base 的右边, 凡是比 base 小的都放在base 的左边, 重复, 直到base 左右两边都是目标顺序.
以 base 作为分割点划分成两个子序列, 使用递归季旭处理,直到全部有序.
为什么 要 先从右往左走呢? 先从左往右走 行吗?答案是不行的, 因为我们要满足一个条件, 左右哨兵相遇的时候, 对应的元素要小于基准.
比如:
5 0 3 9 8 6
如上,我们将5作为基数。
假设从左边开始(与正确程序正好相反)
于是ls 会移动到数字 9 那个位置停下来,而 rs 原来在 数字 6 那个位置 , ( sentinel ,哨兵)
rs也会移动到数字 9 那个位置停下来. 此时也就是左右哨兵相遇的时候, 对应的元素要大于基准.
此时交换基准 元素和相遇位置的元素.就会出现
9 0 3 5 8 6
明显不对.
而先从右往左走,就会出现左右哨兵相遇的位置 在 3 这个地方, 满足条件.
此时交换基准 元素和相遇位置的元素.就会出现
3 0 5 9 8 6
满足 5 前后都是 顺序序列
#include <stdio.h>
void display(int start, int end);
int a[10] = { 6, 2, 1, 8, 9, 0, 3, 4, 5, 7 };
void quick_sort(int left, int right)
{
int ls = left, rs = right, base = a[left];
if (left > right)
return;
while (ls < rs){
while (ls < rs && a[rs] >= base)//先从右向左走,找小于base 的元素
rs--;
while (ls < rs && a[ls] <= base)//再从左向右走,找大于base 的元素
ls++;
if (ls < rs){// 左右哨兵位置不同则 swap
a[ls] = a[ls] + a[rs];
a[rs] = a[ls] - a[rs];
a[ls] = a[ls] - a[rs];
}
}
//swap base, 此时,左右哨兵位置相同
if (left != ls){
a[left] = a[ls];
a[ls] = base;
}
quick_sort(left, ls - 1);
quick_sort(ls + 1, right);
}
int main(void) {
printf("排序前: ");
display(0, 9);
printf("\n");
quick_sort(0, 9);
printf("\n排序后: ");
display(0, 9);
printf("\n");
return 0;
}
void display(int start, int end)
{
int k = 0;
for (k = start; k <= end; k++)
{
printf("%d ", a[k]);
}
}