- 快速排序基本思想
快速排序是基于分治的思想实现的。一个有序的序列总可以分为两部分:找一个基准值把序列一分为二,左边的区间中原始值总是小于等于基准值,右边区间中元素值总数大于等于基准值。对左右两个区间采用相同的方法直到子区间的元素个数为1,则每个基准值的位置都已正确归位置。
基本实现思路:
①.选取一个基准值,一般选择起始位置的值。
②.左右两端开始遍历,右侧区间中找一个小于基准值的位置停下,左侧区间中找一个大于基准值的位置停下,然后交互两个位置的值。
③.重复②③直到左右指针相遇。
④.交换基准位置和相遇点的值,使基准值归位。
⑤.同样方法递归相遇位置的左右两个子区间,直到没个点都归位。
要让右侧指针先走,以使左右指针相遇在小于基准值的点上,然后可以交换到正确的位置。 - 快速排序代码实现
void qickSort(int left, int right, vector<int>& nums)
{
int i = left;
int j = right;
if (left > right) return;
int temp = nums[left];
while (i != j)
{
while (nums[j] >= temp && i < j)
{
j--;
}
while (nums[i] <= temp && i < j)
{
i++;
}
if (i < j)
swap(nums[i],nums[j]);
}
swap(nums[left],nums[j]);
qickSort(left, i - 1, nums);
qickSort(i + 1, right, nums);
}
- 三路快速排序算法
三路快速排序是把序列分为了三个区间,然后遍历当前序列,判断当前元素需要并入哪个区间即可:
区间1中元素全部<temp,用lt表示该区间最右边位置;
区间2中元素全部等于temp,此区间不用再进入递归;
区间3中元素全部>temp,用rt表示该区间最左侧位置;
仅需要递归区间1和区间2
①.当前值小于基准值
cur<temp,则需要把元素i并入<temp的区间:交换i和lt的下个位置的值,然后lt加1使<temp的区间增1;i位置交互过来的值是遍历过的,需要把i加1。
②.当前值大于基准值
cur>temp,则需要把元素i并入>temp的区间:交换i和rt的前一个位置的值,然后rt减1使>temp区间增1;因为i位置交互过来的值是未遍历到的,此时i不变。
③.当前值等于基准值
cur=temp,则需要把元素i并入==temp区间,此时仅i加1即可。 - 三路快速排序代码实现
void qicksort(int left,int right,vector<int>& nums)
{
if( left > right ) return;
int temp = nums[left];
int lt= left;
int rt = right+1;
int i = left+1;
while( i < rt)
{
if( nums[i] > temp)
{
swap(nums[i],nums[rt-1]);
rt--;
}
else if( nums[i] < temp )
{
swap(nums[i],nums[lt+1]);
lt++;
i++;
}
else
{
i++;
}
}
swap(nums[left],nums[lt]);
qicksort(left,lt-1,nums);
qicksort(rt,right,nums);
}
- 用随机数优化
#include <cstdlib>
#include <time.h>
using namespace std;
srand(time(NULL));
int RAND = (rand() % (right - left) + left);
swap(nums[left], nums[RAND]);