快速排序实在实践中最快的已知排序算法,它的平均运行时间为O(N*logN),最坏的情形为O(N*N)。与归并排序一样,快速排序也是一种分治的递归算法,在分割阶段就是把所有小元素移动到数组的左边而把大元素移到数组的右边,小和大是相对于枢纽元而言的。
首先在选取枢纽元的方法上,我们用三数中值分割法,去左元素,中间元素,和右元素,先给三个元素排序,中间的取为枢纽,要把枢纽元素放到倒数第二个位置,枢纽的选取算法如下所示:
int Center3(int a[],int left,int right)//交换三个元素的位置
{
int center=(left+right)/2;
if(a[left]>a[center])
swap(a[left],a[center]);
if(a[left]>a[right])
swap(a[left],a[right]);
if(a[center]>a[right])
swap(a[center],a[right]);
swap(a[center],a[right-1]);
return a[right-1];
}
接下来就是快速排序的主例程了,i从左到右扫描,如果小于枢纽则++,如果大于枢纽则和j的元素互换;同样的j从右到左扫描,如果大于枢纽则--,如果小于枢纽则和i互换,最后再把枢纽元素放到i和j相等的位置。重复此过程分别递归左右两半部分即可。
void QuickSort(int a[],int left,int right)//快速排序的算法
{
int i,j,p;
if(left+3<=right)
{
p=Center3(a,left,right);//p是枢纽元素
i=left;
j=right-1;
for(;;)
{
while(a[++i]<p)
{}
while(a[--j]>p)
{}
if(i<j)
swap(a[i],a[j]);
else
break;
}
swap(a[i],a[right-1]);//重新把枢纽放到中间位置
QuickSort(a,left,i-1);
QuickSort(a,i+1,right);
}
else
InsertSort(a+left,right-left+1);
}
需要注意的是,对于很小的数组,快速排序是不如插入排序的,所以我加了一个判断条件,可以调用插入排序,插入排序的算法请查阅我先前的文章。