基本思想
用分治的思想,在序列中选取一个基准数,把序列分成两个部分,一个部分比基准数小,一部分比基准数大,这样数列就被分成了两个部分,这两个部分间是有序的,然后就使用递归的思想,继续划分这两个部分,直到每个部分的数据个数都为1。
算法思路
1. 假定将序列头作为基准数, 那么可以看成是将数列头提取出来的,需要在剩余的序列中找到一个数填进去。
2. 要将序列分出两个部分,左边的小于基准数,右边的大于基准数
3. 要保证 2 的话,则应该从右边开始遍历,找到第一个小于基准数的扔到左边去,找到的数的右边都是大于基准数的。此时可看成 右边 的部分少了一个大于基准数的数,那么就应该从左边开始遍历,找到第一个大于基准数的数扔到右边去,依次类推。如此可以保证左边、右边的部分都符合基本思路。
4. 当分出的两个部分的序列大于 1 的时候,则再对每个序列进行依次快排序
示例:
// 升序,左起
/*初始值*/ 3, 7, 5, 1, 2, 4, 9, 6, 10, 8
// 将 3 设为基准数,基准数是 第 1 个,从右边起找到第一个小于 3 的数、交换、记录其位置
/*第一趟*/ 2, 7, 5, 1, 3, 4, 9, 6, 10, 8
// 基准数 是 第5个。此时 第5个 右边的数都比 3 大,然后从左起找第一个大于 3 的数、交换、记录其位置
/*第二趟*/ 2, 3, 5, 1, 7, 4, 9, 6, 10, 8
// 基准数 是 第2个。此时,第2个 左边的数都比 3 小,第5个 右边的数都比3大。接下来从 第5个 起向左找第一个小于 3 的数、交换、记录其位置
/*第三趟*/ 2, 1, 5, 3, 7, 4, 9, 6, 10, 8
// 基准数 是 第4个。此时,第2个 左边的数都比 3 小,第4个 右边的数都比3大。 接下来从 第2个 起向右找第一个大于 3 的数、交换、记录其位置
/*第四趟*/ 2, 1, 3, 5, 7, 4, 9, 6, 10, 8
// 基准数 是 第3个。此时,第3个 左边的数都比 3 小,第4个 右边的数都比3大。 接下来从 第4个 起向右找第一个小于 3 的数、交换、记录其位置
// 此时,已顺利将序列 以第三个为界限 分为两个部分,左边的部分所有值、都比右边的部分小
重点:
如何高效的将序列分为小于/大于基准数的两个个部分。
思路:
1. 在与基准数比较的时候,从右往左找到第一个小于基准数后,假设 index 为 m, 则此时 m 右边的值都是大于基准数的。此时,再将 m 与序列左边起第一个尚未与基准数比较过的位置交换,设该 index 为 n,即、将比基准数小的扔到了的左边。
2. 此时,可以保证的是,m 、不包括m 、右边的都比基准数大,n、包括n、左边的都比基准数小, m为基准数。
3. 下一个要找的数是 比基准数 大的,放在 m 的位置。
4. 所以接下来,从 n 开始往右遍历,找到第一个比 基准数 大的,假设 index 为 n1,然后放到 m 的位置。
5. 此时,可以保证的是, m 、包括m 、右边的都比基准数大, n1、不包括n1、左边的都比基准数小, n1 为基准数。
6. 下一个要找的数是 比基准数 小的,放在 n1 的位置。
7. 所以接下来,从 m 开始往左遍历,找到第一个比 基准数 大的,假设 index 为 m1,然后放到 n1 的位置。
代码:
void printList(int *l, int n) {
for (int i = 0; i < n; i++) {
printf("%d ", l[i]);
}
printf("\n");
}
void swap(int &m, int &n) {
int j = m;
m = n;
n = j;
}
void quickSort(int l[], int lenth ) {
if (lenth > 1) {
int index = 0;
// 升序
bool left = false;
printf("\nquik sort start\n");
printList(l, lenth);
for (int i = 0, j = lenth - 1; i < j;) {
printf("left: %d, i;%d, j:%d, index: %d\n", left, i, j, index);
if ( left ) {
// 从左往右 找第一个大于 l[index] 的
if (l[i] > l[index]) {
swap(l[i], l[index]);
index = i;
// 变更遍历方向
left = false;
printList(l, lenth);
}
else {
i++;
}
} else {
// 从右往左 找第一个小于 l[index] 的
if ( l[j] < l[index]) {
swap(l[j], l[index]);
index = j;
// 变更遍历方向
left = true;
printList(l, lenth);
}
else {
j--;
}
}
}
printList(l, lenth);
printf("quik sort end\n");
// 迭代左边部分和右边部分
quickSort(l, index);
quickSort(l + index + 1, lenth - index - 1);
}
}
int main()
{
int a[10] = { 3,7,5,1,2,4,9,6,10,8 };
printf("初始值:");
printList(a, 10);
quickSort(a, 10);
printf("结果:");
printList(a, 10);
system("pause");
return 0;
}
以上
原文链接 http://blog.youkuaiyun.com/u011546766/article/details/74055269