快速排序
快速排序是一种利用了分治法的排序方法,在数组中寻找一个基准量(数组第一个值或者随机选取某个值)每次循环过程中,将待排序的数组分成两组,小于基准量的值位于数组的左侧,大于基准量的值位于数组的右侧,这样每次循环均能够寻找到基准量在数组中的正确位置。
快速排序主要的步骤就是,使用基准量划分数组,然后对划分的数组进行排序。
例如数组:
4 3 5 11 3 7 2 9
将第一个值4当成基准量,那么第一次循环后得到的结果为:
3 3 2 4 11 7 5 9
那么这个结果是如何得到的呢?最简单的方法是交换指针法:
固定基准值4,使用两个指针遍历调整数组满足小于基准值的在左侧,大于的在右侧,指针设为left,right,如下图所示,一次划分的操作:
复杂度
快速排序的平均复杂度为 O(nlgn) O ( n l g n ) ,最坏情况为 O(n2) O ( n 2 ) ,可以简单看成平均的划分操作的次数为 O(lgn) O ( l g n ) ,每次划分为 O(n) O ( n ) 。为了提高性能,有时候会采取随机基准值策略。
代码
划分函数
int partional(vector<int> &a,int lo,int hi){
int i=lo+1,j=hi;
int temp;
while(true){
while(a[i]<a[lo]&&i<hi)
i++;
while(a[j]>a[lo]&&j>lo)
j--;
if(i>=j)break;
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
temp=a[lo];
a[lo]=a[j];
a[j]=temp;
return j;
}
排序部分
排序部分可以采用递归,也可以采用非递归
递归型
void quicksort(vector<int> &a,int lo,int hi){
if(lo>=hi) return;
int p=partional(a,lo,hi);
quicksort(a,lo,p-1);
quicksort(a,p+1,hi);
}
非递归型
非递归相较于递归需要用一个栈维护划分的数组的范围,如下图所示:
void quicksort(vector<int> &a){
int lo=0,hi=a.size()-1;
int p;
stack<int> sc;
sc.push(lo);
sc.push(hi);
while(!sc.empty())
{
hi=sc.top();
sc.pop();
lo=sc.top();
sc.pop();
p=partional(a,lo,hi);
if(p>lo){
sc.push(lo);
sc.push(p-1);
}
if(p<hi){
sc.push(p+1);
sc.push(hi);
}
}
}