快排基本思想-快排是一种交换排序,是一种二叉树结构的排序方法,采用分治递归的思想;从待排序数组中取一个数,称为key/pivot-基数,遍历数组将比key大的数字放在key的右边,将比key小的数字放在key的左边,遍历完成后,数组被分成了左右两个区域,将左右两个区域视为两个数组,重复前两个步骤,直到排序完成
将区间按照key划分为左右两部分的方法:
1.左右指针法
//左右指针法
int partsort1(vector<int>&nums, int left, int right){
int mid = getmid(nums, left, right);
swap(nums[right], nums[mid]);
int key = nums[right];
int keyindex = right;
while (left < right){
while (left < right&&nums[left] <= key){
left++;
}
while (left < right&&nums[right] >= key){
right--;
}
swap(nums[left], nums[right]);
}
swap(nums[left], nums[keyindex]);
return left;
}
2.挖坑法
//挖坑法
int partsort2(vector<int>&nums, int left, int right){
int mid = getmid(nums, left, right);
swap(nums[right], nums[mid]);
int key = nums[right];
while (left < right){
while (left < right&&nums[left] <= key){
left++;
}
nums[right] = nums[left];
while (left < right&&nums[right] >= key){
right--;
}
nums[left] = nums[right];
}
nums[left] = key;
return left;
}
![](https://i-blog.csdnimg.cn/blog_migrate/a25fdd59782fe33c56f0c97420ff29eb.png)
3.前后指针法
//前后指针法
int partsort3(vector<int>&nums, int left, int right){
int prev = left - 1;
int cur = left;
int mid = getmid(nums, left, right);
swap(nums[right], nums[mid]);
int key = nums[right];
while (cur < right){
if (nums[cur] < key&&prev++ != cur){
swap(nums[prev], nums[cur]);
}
cur++;
}
prev++;
swap(nums[prev], nums[right]);
return prev;
}
快排什么时候最坏?-
有序的情况下
最坏情况的优化?-
三数取中法选key
int getmid(vector<int>&nums, int left, int right){
int mid = (left + right) >> 1;
//1-left<mid
if (nums[left] < nums[mid]){
//1.1-right left mid
if (nums[right] < nums[left]){
return left;
//1.2-left mid right
}
else if (nums[mid] < nums[right]){
return mid;
}
else{//1.3-left right mid
return right;
}
}
else{//2-mid<left
//2.1-right mid left
if (nums[right] < nums[mid]){
return mid;
//2.2-mid left right
}
else if (nums[left] < nums[right]){
return left;
}
else{//2.3-mid right left
return right;
}
}
}
快排非递归-用stack栈
递归-调用太多导致开辟栈帧太多-栈溢出
非递归-用栈-在堆上开辟空间-非递归借助栈达到递归
class Solution {
public:
int partsort2(vector<int>&nums, int left, int right){
int key = nums[right];
while (left < right){
while (left < right&&nums[left] <= key){
left++;
}
//左边坑出来了
nums[right] = nums[left];
while (left < right&&nums[right] >= key){
right--;
}
//右边坑出来了
nums[left] = nums[right];
}
nums[left] = key;
return left;
}
void quicksortstack(vector<int>&nums, int left, int right){
stack<int>st;
st.push(left);
st.push(right);
while (!st.empty()){
int right = st.top();
st.pop();
int left = st.top();
st.pop();
int pos = partsort2(nums, left, right);
if (left < pos - 1){
st.push(left);
st.push(pos - 1);
}
if (pos + 1 < right){
st.push(pos + 1);
st.push(right);
}
}
}
vector<int> sortArray(vector<int>& nums) {
int left = 0;
int right = nums.size() - 1;
quicksortstack(nums, left, right);
return nums;
}
};
快排特性
不稳定
时间复杂度nlogn
空间复杂度1
class Solution {
public:
int partsort2(vector<int>&nums, int left, int right){
int key = nums[right];
while (left < right){
while (left < right&&nums[left] <= key){
left++;
}
//左边坑出来了
nums[right] = nums[left];
while (left < right&&nums[right] >= key){
right--;
}
//右边坑出来了
nums[left] = nums[right];
}
nums[left] = key;
return left;
}
void quicksort(vector<int>&nums, int left, int right){
//递归终止条件
if (left >= right){
return;
}
int pos = partsort2(nums, left, right);
quicksort(nums, left, pos - 1);
quicksort(nums, pos + 1, right);
}
vector<int> sortArray(vector<int>& nums) {
int left = 0;
int right = nums.size() - 1;
quicksort(nums, left, right);
return nums;
}
};
测试用例-
[6,1,2,7,9,3,4,5,10,8]