时间复杂度为:平均为nlog(n),最坏为n²,但很难达到最坏情况
空间复杂度为:O(1),不需要辅助数组,归并排序需要一个O(n)的辅助数组
快速排序第一种写法:
#include<bits/stdc++.h>
using namespace std;
int n, a[100005];
void quickSort(int *a, int l, int r){
if(l >= r)
return ;
int mid = a[(l+r)/2];
int left = l, right = r;
while(true){
//因为基准取得是(l+r)/2,所以不需要限制right和left的边界条件
//所有不需要 right >= l 和 left <= r
while(mid < a[right]){
--right;
}
while(mid > a[left]){
++left;
}
if(left > right){
break;
}
swap(a[left], a[right]);
++left;
--right;
}
quickSort(a, l, right);
quickSort(a, left, r);
return ;
}
int main(){
scanf("%d", &n);
for(int i=1; i<=n; ++i){
scanf("%d", &a[i]);
}
quickSort(a, 1, n);
for(int i=1; i<=n; ++i){
printf("%d ",a[i]);
}
return 0;
}
快速排序的第二种写法:
#include<bits/stdc++.h>
using namespace std;
int a[100005], n;
void quickSort(int *a, int l, int r){
if(l >= r){
return ;
}
//随机取基准,将a[l]作为基准
swap(a[l], a[l+rand()%(r-l+1)]);
int i = l+1, j = r, mid = a[l];
while(true){
while(j >= l+1 && mid < a[j]) --j;
while(i <= r && mid > a[i]) ++i;
if(i > j){
break;
}
swap(a[i], a[j]);
++i;
--j;
}
//保证当前区间的第j个元素的位置是一定正确的,
//也就是基准所在位置一定正确
//因为基准前面和后面的元素一定都小于等于基准
swap(a[l], a[j]);
quickSort(a, l, j-1);
quickSort(a, j+1, r);
return ;
}
int main(){
scanf("%d", &n);
for(int i=1; i<=n; ++i){
scanf("%d", &a[i]);
}
quickSort(a, 1, n);
for(int i=1; i<=n; ++i){
printf("%d ",a[i]);
}
return 0;
}
应用:
数组第k大:
#include<bits/stdc++.h>
using namespace std;
int getKthNum(vector<int> &a, int l, int r, int k){
swap(a[l], a[l+rand()%(r-l+1)]);
int i=l+1, j=r, mid = a[l];
while(true){
//降序
while(j >= l+1 && a[j] < mid) --j;
while(i <= r && a[i] > mid) ++i;
if(i>j){
break;
}
swap(a[i], a[j]);
++i;
--j;
}
swap(a[l], a[j]); //这个交换保证了在[l, r]中第k大在第k位上
if(j+1 == k){
return a[j];
}
else if(j+1 > k){
return getKthNum(a, l, j-1, k);
}
else{
return getKthNum(a, j+1, r, k);
}
}
int main(){
vector<int> a = {1,3,5,2,2};
cout<<getKthNum(a, 0, a.size()-1, 3);
return 0;
}