排序算法--快速排序

快速排序是一种分治排序算法,将数组分为两个部分,然后分别对两个部分进行排序。划分过程是不稳定的,因为每个元素都有可能在交换时被移到大量与它相等的元素(未经检测)后面。

划分过程如下:
选择一个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 ];                  /* 返回该中值 */
}

猜你喜欢

转载自blog.csdn.net/u010034085/article/details/79983752