概述
快速排序是 C 语言库中常用的高效排序算法。本文将介绍从基础到高阶的快速排序实现,包括多种优化策略。
一、快速排序(初阶)
1. 算法思想
快速排序有一个基准元素(key),通常选择数组的第一个数字。排序结束后,key 左边的数都小于它,右边的数都大于它。然后以 key 为界将数组分为两个区间,递归处理这两个区间,直到区间不可再分。
一句话总结,快速排序就是不断将比 key 小的数放左边,把比 key 大的数放右边,最后完成排序。
2. 实现思路
(1)定 key 值
第一步:定 key 值。快速排序有一个 key 值,叫基准元素,现在可以理解为就是第一个数字(后续还会再改进)。后续的排序就是围绕这个基准元素 key 来进行的。
(2)大小交换
第二步:大小交换。使用两个指针,一个从左向右找比 key 大的数,一个从右向左找比 key 小的数,相遇前交换。
(3)循环
第三步:循环。两指针继续移动,满足条件时继续交换,然后重复,直到两指针相遇循环停止。
(4)交换 key
第四步:交换 key。此时将 key 与两指针相遇点的值进行交换。此时在 key 的左边都是小于 key 的数,在 key 的右边都是大于 key 的数。此时 key 就已经排好序,后续也不需要再动,第一轮快速排序结束。
(5)分割区间
第五步:分割区间。现在 key 就已经排好序,后续也不需要再动。此时将 key 左右的区间分割开来,分成左右两个区间。然后分别对这两个区间重复第一轮的排序:定 key 值、大小交换、循环、交换 key、分割区间。
(6)结束
第六步:结束。当每个区间分割成只剩下一个元素时,自然也不需要继续循环,就可以跳出循环。当所有的区间都只剩下一个元素时,都跳出循环时,排序也就完成了。
3. 实现代码
void QuickSort1(int* a, int left, int right) {
if (left >= right) // 判断是否继续,当区间只有一个数时跳出循环
return;
int key = left; // 确定 key 的值,为第一个元素
int L = left;
int R = right; // 先将左右的下标记录下来,以免后面丢失
while (left < right) { // 当左右小人相遇时就停止循环
while (left < right && a[right] >= a[key]) // 右小人向左走,直到找到比 key 小的值
right--;
while (left < right && a[left] <= a[key]) // 左小人向右走,直到找到比 key 大的值
left++;
Swap(&a[left], &a[right]); // 交换大的值和小的值
}
Swap(&a[right], &a[key]); // 最后交换 key 和相遇点对应的值
key = right;
QuickSort1(a, L, key - );
QuickSort1(a, key + , R);
}


