快速排序时间复杂度为O(nlogn),由于每次主元所在次序并不一定是在数列中央,所以复杂度并不是确定的。
特殊的,当原数组排序程度越高的时候,快速排序时间复杂度会退化,当原数组完全有序时,快速排序时间复杂度退化成O(n^2)
确定主元排序:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100+5;
int a[maxn];
void quick_sort(int left,int right)
{
if(left>=right) return;
//选取主元
int temp = a[left];
int i = left;
int j = right;
while(i!=j)
{
while(a[j]>=temp&&i<j)
j--;
while(a[i]<=temp&&i<j)
i++;
swap(a[i],a[j]);
}
swap(a[left],a[i]);
quick_sort(left,i-1);
quick_sort(i+1,right);
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
quick_sort(0,n-1); //左闭右闭
for(int i=0;i<n;i++)
printf("%d%c",a[i],i==n-1?'\n':' ');
return 0;
}
注意其中左闭右闭的写法,避免数组下标越界产生问题;
同时,要注意选定主元后,必须是先从后找小于主元的数,再从前找大于主元的数,这样是为了避免最后i和j相等的时候,主元交换了一个大于它的数,造成乱序错误;
随机化主元:
//随机化快速排序
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100+5;
int a[maxn];
int rand(int l,int r)
{
srand(time(NULL));
return rand()%(r-l+1)+l;
}
void quick_sort(int left,int right)
{
if(left>=right) return;
//随机选取主元,对于原数组有序程度高的情况下,时间复杂度会退化成O(n^2) 这时采用随机化算法使得复杂度稳定在O(nlogn)
int k = rand(left,right);
int temp = a[k];
int i = left;
int j = right;
swap(a[left],a[k]);
while(i!=j)
{
while(a[j]>=temp&&i<j)
j--;
while(a[i]<=temp&&i<j)
i++;
swap(a[i],a[j]);
}
swap(a[left],a[i]);
quick_sort(left,i-1);
quick_sort(i+1,right);
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
quick_sort(0,n-1); //左闭右闭
for(int i=0;i<n;i++)
printf("%d%c",a[i],i==n-1?'\n':' ');
return 0;
}
三路快排:当重复元素过多的时候,快速排序时间复杂度会退化成O(n^2),这时采用三路快排,加入随机选取主元
参考博客:https://www.imooc.com/article/16141
//三路快排 + 随机选取主元 可以避免快速排序复杂度退化的问题
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000+5;
int rand(int l,int r)
{
srand(time(NULL));
return rand()%(r-l+1)+l;
}
void quick_sort(int l,int r,int *a,int len)
{
if(l>=r) return;
if(a==nullptr) return;
//完成一次3路快排
//随机选取主元
int temp =*(a+rand(l,r));
int rzero = l; //指向第一个temp元素位置 以及小于temp元素的边界位置
int rone = l;
int ltwo = r; //指向下一个大于主元的数所存放的位置
while(rone<=ltwo)
{
if(*(a+rone)==temp) {
rone++;
}
else if(*(a+rone)<temp) {
swap(*(a+rone),*(a+rzero));
rzero++,rone++;
}
else if(*(a+rone)>temp) {
swap(*(a+rone),*(a+ltwo));
ltwo--;
}
}
if(*(a+ltwo)==temp) ltwo++;
if(rone>=len||nums[rone]!=temp) rone--;
quick_sort(l,rzero-1,a);
quick_sort(ltwo,r,a);
}
int main()
{
int n,a[maxn];
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
quick_sort(0,n-1,a,n);
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}