快速排序

来源:互联网 发布:初级网络优化工程师 编辑:程序博客网 时间:2024/06/11 08:11

顾名思义,快速排序(quicksort)是在实践中最快的一致排序算法,它的平均运行时间是O(NlogN)。该算法之所以特别快,主要是由于非常精炼和高度优化的内部循环。它的最坏情形的性能为O(N^2),但稍加努力就可以改变这种情形。
像归并排序一样,快速排序也是一种分治的递归算法。将数组S排序的基本算法由下列简单的四步组成:
(1)如果S中元素个数是0或1,则返回。
(2)取S中任一元素v,称之为枢纽元(pivot)。
(3)将S-{v}(S中其余元素)划分成两个不相交的集合:S1={x属于S-{v} ,x<=v}和S2={x属于S-{v}|x>=v}。
(4)返回{quicksort(S1),后跟v,继而{quciksort(S2)}.
选取枢纽元的方法
三数中值分割法:
一组N个数的中值是第N/2个最大的数。枢纽元的最好的选择是数组的中值。可是,这很难算出,并且会明显减慢快速排序的速度。这样的中值并没有多大的帮助,因此一般的做法是使用左端,右端和中心位置上的三个元素的中值作为枢纽元。例如,输入为8,1,4,9,6,3,5,2,7,0,它的左边元素是8,右边元素是0,中心位置上的元素是6。于是枢纽元则是v=6。显然使用三数中值分割法消除了预排序输入的不好情形。
小数组
对于很小的数组(N<=20),快速排序不如插入排序好。而且,因为快速排序是递归的,所以这样的情形经常发生。通常的解决方法是,对于小的数组不递归地使用快速排序,而代之以诸如插入排序这样的对小数组有效的排序算法。使用这种策略大约可以节省15%的时间。一种好的截止范围是N=10,虽然在5~20之间任一截止范围都有可能产生类似的结果。

快速排序的驱动程序/*** Quicksort algorithm (driver).* /template <typename Comparable> void quicksort( vector<Comparable> & a){     quicksort(a,0,a.size() -1 );}执行三数中值分割方法的程序/*** Return median of left, center, and right.* Order these and hide the pivot.* /template <typename Comparable>const Comparable & median3( vector<Comparable> & a, int left,int right){   int center=(left+right) /2 ;   if(a[center] <a[left] )      swap( a[left],a[center]);   if(a[right] <a[left] )       swap(a[left],a[right] );   if(a[right] <a[center] )       swap( a[center],a[right]);      //Place pivot at position right -1, because a[right] > a[center]   swap(a[center],a[right-1]);   return a[right-1];}快速排序的主程序/*** Internal quicksort method that makes recursive calls.* Uses median-of-three partitioning and c cutoff of 10.* a is an array of Comparable items.* left is the left-most index of the subarray.* right is the right-most index of the subarray.* /template <typename Comparable>void quicksort(vector<Comparable> & a, int left, int right){    if( left + 10 <= right )    {        Comparable pivot=median3(a,left,right);             //Begin partitioning         int i=left,j=right-1;         for( ; ; )         {             while(a[++i] < pivot ) {}             while(pivot < a[--j] ) {}             if(i<j)                 swap(a[i],a[j]);             else                  break;         }          swap(a[i],a[right-1] ); //Restore pivot         quicksort(a,left,i-1);  //Sort small elements         quicksort(a,i+1,right);  // Sort large elements    }}
1 0