核心思想:
1:找到哨兵,将哨兵放到数组中间,使得数组左边的数据都小于哨兵,数组右边的元素都大于哨兵
2:递归哨兵左右半边的元素
代码分成两个部分:分别为哨兵划分和递归快排
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<vector>
//哨兵位置查找,并且返回哨兵的位置
int sold(vector<int>& nums, int l, int r) {
int i = l; int j = r;
while (i < j)
{
while (i < j&&nums[j] >= nums[l])
j--; // 最右的指针左移,保证默认哨兵位子(l)一定是小于右边的
while (i < j&&nums[i] <= nums[l])
i++; // 最左的指针右移,保证默认哨兵位子(l)一定是大于左边的
swap(nums[i], nums[j]); // 使得不满足条件的交换位置
}
swap(nums[i], nums[l]); // 找到哨兵中间位置,交换
return i;
}
void quickSort1(vector<int>& nums, int l, int r) {
//判断数组长度为1返回
if (l >= r)
return;
//调用哨兵函数
int i = sold(nums, l, r);
//使用递归,左右分别划分
quickSort1(nums, l, i - 1);
quickSort1(nums, i + 1, r);
}
void quickSort2(vector<int>& nums, int l, int r) {
//判断数组长度为1返回
if (l >= r)
return;
// 子数组长度为 1 时终止递归 其实上边可以不用判断了
while (l < r)
{
//调用哨兵函数
int i = sold(nums, l, r);
//使用递归,左右分别划分
//每轮递归时,仅对较短的子数组执行哨兵划分,可将最差的递归深度控制在 O(logN)
if (r - i > i - l)
{
//左半段比较短小
quickSort2(nums, l, i - 1);
l = i + 1;//再考虑右半段
}
else
{
//右半段比较短小
quickSort2(nums, i + 1, r);
r = i - 1;
}
}
}
void test1() {
vector<int> nums = { 4, 1, 3, 2, 5, 1 };
int r = nums.size() - 1;
quickSort1(nums, 0, r);
for (vector<int>::iterator it = nums.begin(); it != nums.end(); it++)
{
cout << *(it) << " ";
}
cout << endl;
}
void test2() {
vector<int> nums = { 4, 1, 3, 2, 5, 1 };
int r = nums.size() - 1;
quickSort2(nums, 0, r);
for (vector<int>::iterator it = nums.begin(); it != nums.end(); it++)
{
cout << *(it) << " ";
}
cout << endl;
}
int main()
{
test1();
test2();
system("pause");
return EXIT_SUCCESS;
}