目录
思路介绍
快速排序是对冒泡排序算法的一种改进。以一个数为基准,将数组分为两个子序列,左子序列放比基准数小的数,右子序列放比基准数大的数,然后再将子序列以上述方式操作,直到整个数组有序。
步骤
采用挖坑法:
1、定义变量key,存储数组第一个数作为key,左右两个指针指向数组的开头和结尾
2、从右指针开始移动,找到比key值小的,放入左指针的坑里,右指针形成新坑
3、切换到左指针移动,找比key大的值,放入到右指针的坑里,左指针形成新坑
4、依次循环直到左右指针相遇,将key放入到这个坑中
5、之后左右两个子序列递归调用此步骤,直到整个数组有序
代码
void QuickSort(int* arr, int size) {
if (size < 2)return;
int key = arr[0];
int left = 0;
int right = size - 1;
int flag = 2; //标志位为1移动左指针,标志位为2移动右指针
while (left < right) {
if (flag == 2) { //先移动右指针
if (arr[right] >= key) {right--; continue;}
arr[left] = arr[right];
left++;
flag = 1;
continue;
}
if (flag == 1) { //移动左指针
if (arr[left] <= key) { left++; continue; }
arr[right] = arr[left];
right--;
flag = 2;
continue;
}
}
arr[left] = key; //此时left==right
//递归调用左右子序列
QuickSort(arr, left); //左子序列
QuickSort(arr + left + 1, size - left - 1);
}
快速排序的优化代码
优化一
采用更合理的基准数(key),减少递归深度,例如随机选、选中间位置、三值或多值取折中等。
优化二
快速排序时以递归形式对分好大小的两个子序列进行单趟排序,若是递归到较深处时,待排数组较短,但是数量也越多,调用函数的次数就越多,开辟函数栈帧的消耗越大,导致效率下降。因此可以设置一个数组排序的长度下限,若是数组长度到达下限以下,则不再调用快速排序,而是调用插入排序。
void QuickSort2(int* arr, int size) {
if (size < 2)return;
if (size <= 8) { //例如数组长度小于等于8时,调用插入排序
//插入排序
insertSort(arr, size);
return;
}
int key = arr[0];
int left = 0;
int right = size - 1;
int flag = 2; //标志位为1移动左指针,标志位为2移动右指针
while (left < right) {
if (flag == 2) { //先移动右指针
if (arr[right] >= key) { right--; continue; }
arr[left] = arr[right];
left++;
flag = 1;
continue;
}
if (flag == 1) { //移动左指针
if (arr[left] <= key) { left++; continue; }
arr[right] = arr[left];
right--;
flag = 2;
continue;
}
}
arr[left] = key; //此时left==right
//递归调用左右子序列
QuickSort(arr, left); //左子序列
QuickSort(arr + left + 1, size - left - 1);
}