1、快速排序
分治思想。
(1)步骤
(2)代码
- 递归(前序遍历)
class Solution {
public:
vector<int> vec;
vector<int> sortArray(vector<int>& nums) {
vec = nums;
quick_sort(0,nums.size()-1);
return vec;
}
void quick_sort(int left,int right){
if(left>=right) return;
int pivot = partition(left,right);
quick_sort(left,pivot-1);
quick_sort(pivot+1,right);
}
int partition(int left,int right){
int pivot=vec[left];
int i=left,j=right;
while(i<j){
while(i<j && vec[j]>=pivot) --j;
while(i<j && vec[i]<=pivot) ++i;
if(i<j) swap(vec[i],vec[j]);
}
swap(vec[left],vec[i]);
return i;
}
};
- 迭代
class Solution {
public:
vector<int> vec;
vector<int> sortArray(vector<int>& nums) {
vec=nums;
stack<pair<int,int>> s;//类型由quick_sort()函数的参数决定
s.push({0,vec.size()-1});
while(!s.empty()){
auto [low,high]=s.top();
s.pop();
int pos=partition(low,high);
if(low<pos-1) s.push({low,pos-1});
if(pos+1<high) s.push({pos+1,high});
}
return vec;
}
int partition(int low,int high){
int pivot=vec[low];
int i=low,j=high;
while(i<j){
while(i<j && vec[j]>=pivot) --j;
while(i<j && vec[i]<=pivot) ++i;
if(i<j) swap(vec[i],vec[j]);
}
swap(vec[low],vec[i]);
return i;
}
}
- 特殊处理
当取左右端点超时时,可以使用随机值或者中间值来与第一个元素交换,然后再取左端点作为基准。
swap(nums[left],nums[rand()%(right-left+1)+left]);
int pivot = nums[left];
- 复杂度
时间:平均O(nlogn)
空间:O(logn)
稳定性:不稳定
变为稳定的方法:使用pair来存储值和索引,二个判断。
在C++中,当输入的数据比较多时,最好使用scanf来输入,不要使用cin来输入。
2、快速排序
分治思想。
(1)步骤
(2)代码
- 递归(后序遍历)
class Solution {
public:
vector<int> res;//临时存放,然会再合并到原数组
vector<int> sortArray(vector<int>& nums) {
res.resize(nums.size(),0);
merge_sort(nums,0,nums.size()-1);//[0,size]
return nums;
}
void merge(vector<int>& nums,int first,int last,int mid){
int i=first,j=mid+1,k=0;
while(i<=mid && j<=last) res[k++]=nums[i]<nums[j]?nums[i++]:nums[j++];
while(i<=mid) res[k++]=nums[i++];
while(j<=last) res[k++]=nums[j++];
for(int i=0;i<last-first+1;++i) nums[i+first]=res[i];
}
void merge_sort(vector<int>& nums,int first,int last){
if(first>=last) return;
int mid=first+(last-first)/2;
merge_sort(nums,first,mid);
merge_sort(nums,mid+1,last);
merge(nums,first,last,mid);
}
}
- 迭代
class Solution {
public:
vector<int> tmp;
vector<int> sortArray(vector<int>& nums) {
tmp.resize(nums.size(),0);
mergesort(nums,0,nums.size()-1);
return nums;
}
void mergesort(vector<int>& nums,int first,int last){
stack<pair<int,int>> s;//用来存放区间范围
stack<tuple<int,int,int>> ss;//用来存放left,right,mid的
if(first<last) s.push({first,last});
while(!s.empty()){
auto [left,right] = s.top();
s.pop();
int mid = left+(right-left)/2;
ss.push({left,right,mid});
if(left<mid) s.push({left,mid});
if(mid+1<right) s.push({mid+1,right});
}
while(!ss.empty()){
auto [left,right,mid] = ss.top();
ss.pop();
merge(nums,left,right,mid);
}
}
void merge(vector<int>& nums,int first,int last,int mid){
int i=first,j=mid+1,k=0;
while(i<=mid && j<=last) tmp[k++]=nums[i]>nums[j]?nums[j++]:nums[i++];
while(i<=mid) tmp[k++]=nums[i++];
while(j<=last) tmp[k++]=nums[j++];
for(int i=0;i<k;++i){
nums[first+i]=tmp[i];
}
}
};
- 复杂度
时间:O(nlogn)(虽然每次划分不是平均的,但是期望是n/2)
空间:需要增加额外空间n+log2(n)(临时数组n和递归调用函数栈log2(n)),空间复杂度为O(n))
稳定性:稳定