快速排序是一种分治排序算法,将数组分为两个部分,然后分别对两个部分进行排序。划分过程是不稳定的,因为每个元素都有可能在交换时被移到大量与它相等的元素(未经检测)后面。
划分过程如下:选择一个a[r]作为划分元素,这个元素在划分后将在最终的位置上。
然后从数组的左端进行扫描,直到找到一个大于划分元素的元素。
同时从数组的右端开始扫描,直到找到一个小于划分元素的元素。
使扫描停止的这两个元素,显然在最终的划分数组中位置相反,于是交换这两个元素,继续这一过程。
划分结果如下:
1.对于某个i,a[i]在数组的最终位置上。(划分过程至少(划分元素)将一个元素放在它最终所在的位置)
2.a[l]~a[i-1]中的元素都比a[i]小(或等于)。
3.a[i+1]~a[r]中的元素都比a[i]大(或等于)。
我们通过划分来完成排序,然后递归的应用该方法处理子文件。
保证递归终止的方法:
1.不对小于等于1的文件进行递归调用。
2.只对比给定输入小的文件递归调用。
3.当划分元素是最大/小值的时候,会使得陷入无限递归状态。一般采用三者取中法来规避。
void Quicksort( ElementType A[ ], int N ) { Qsort( A, 0, N - 1 ); } void Qsort( ElementType A[ ], int Left, int Right ) { int i, j; ElementType Pivot; Pivot = Median3( A, Left, Right ); i = Left; j = Right - 1;/*注意 i,j 的起始位置,并参考 ++i 与 ++j。*/ for( ; ; ) { while( A[ ++i ] < Pivot ){ }/*从左开始,比划分元素小,则指针向左移动 ; 若大于等于,则停止移动*/ while( A[ --j ] > Pivot ){ } if( i < j )/*左右指针未相遇*/ Swap( &A[ i ], &A[ j ] );/*左右指针都停止,若没相遇,则交换指向元素*/ else break;/*左右指针都停止,若已经相遇,则停止交换动作,结束*/ } Swap( &A[ i ], &A[ Right - 1 ] ); /*将划分元素放入指针相遇之后i位置,即最后正确位置 */ Qsort( A, Left, i - 1 );/*左部递归*/ Qsort( A, i + 1, Right );/*右部递归*/ } /* Return median of Left, Center, and Right */ /* Order these and hide the pivot */ ElementType Median3( ElementType 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 ] ); /* 最终左中右按照 从小到大顺序: A[ Left ] <= A[ Center ] <= A[ Right ] */ Swap( &A[ Center ], &A[ Right - 1 ] ); /* 将中值放到 倒数第二 Right - 1 的位置 */ return A[ Right - 1 ]; /* 返回该中值 */ }