算法思想
数组排序任务可以如下完成:
1)设k=a[0],将k挪到适当位置,使得比k小的元素都在k的左边,比k大的元素都在k的右边,和k相等的,不关心在k左右出现均可(O(n)时间完成)
2)把k左边的部分快速排序
3)把k右边的部分快速排序
(假设运气比较好,每次基准元素被移动到中间,这样的话时间复杂度为O(nlogn))
如何在O(n)的时间内将数组分成两半,一般在小于基准值,一般大于基准值?
程序代码
#include<iostream>
using namespace std;
int a[100];
//交换a,b的值
void swap(int &a,int &b){
int temp=a;
a=b;
b=temp;
}
void quickSort(int start,int end){
if(start<end){
//将数组首元素设为基准值
int temp=a[start];
//定义两个指针i,j分别指向数组的头部和尾部
int i=start,j=end;
while(i<j){
//偶数次交换之后,就不停的让a[j]和temp相比,此时temp是a[i]
while((i<j)&&(a[j]>=temp)){
j--;
}
//当i=j或者a[j]<temp的时候,就进行交换
swap(a[j],a[i]);
//奇数次交换之后,就不停的让a[i]和temp相比,此时temp是a[j]
while((i<j)&&(a[i]<=temp)){
i++;
}
//当i=j或者a[i]>temp的时候,就进行交换
swap(a[j],a[i]);
}
//处理完后,a[i]=k
//划分完成后,对i左边的和右边的分别进行快速排序,但是a[i] 一定不参与排序
quickSort(start,i-1);
quickSort(i+1,end);
}
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
quickSort(0,n-1);
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
return 0;
}
时间复杂度分析
当每次划分元素的时候,左右两边的元素的个数相等,这个时候,是快速排序最好的一种情况,其时间复杂度为O(nlogn),与归并排序类似
当每次划分元素的时候,一边的元素个数为0,这个时候,是快速排序最坏的一种情况,其时间复杂度为O(n2),此时,序列通常为有序。
一般情况下,快速排序的时间复杂度是O(nlogn)
快速排序具有广泛的应用,通常认为是性能最高的排序算法,在c++的algorithm文件中的sort函数所用到的正是快速排序。
知识拓展:快速排序为何最快
我们都知道,归并排序,堆排序的时间复杂度均为O(nlogn),为何快速排序就最快了呢,因为快速排序每次都会与一个基准值做比较,如果我们把这个基准值放在寄存器里,由于寄存器的速度远远大于cache和主存的速度,所以快速排序的性能将会得到巨大的提升,所以快速排序的性能最优。