快速排序(Quicksort)

0)引论

人如其名,快速排序之所以称之为快速排序就是因为在实践中,这个算法是最快的排序算法。它的平均运行时间为O(NlogN)。最坏的时间复杂度为O(N^2)。虽然像堆排序,归并排序的时间复杂度比较低,但是他们的实际运行时间并不比快速排序快,反而由于有一些拷贝的进程,使运行时间变得很慢。快速排序也是一种divide-and-conquer策略。


1)快速排序基本步骤:

a) 如果数据集S中的元素个数为0或1,则返回。

b) 选取S中的一个元素v,我们称这个元素v为pivot。

c) 把S-{v}分成两部分S1 = {x<=v} ,S2 = {x>=v}。

d) 返回quicksort(S1) , v, quicksort(S2)。



2)pivot的选择

pivot的选择是一个很大的问题。因为pivot直接影响到分开的两组数据的个数,而如果这两组数据是不均衡的,则会严重影响到算法的运行速度。举个例子来说,如果每次选择的pivot 都是最大值的话,那么这个快速排序算法相当于插入排序

pivot的选择有以下几种

a) 选取第一个值。这种算法适用于随机分布的数据。如果是一个有序的序列,那么这种选取方式就是一个灾难啊,将会不断的递归,也没有什么本质的提高

b) 随机选取一个值。这种方法也是看运气,如果选择了一个好的值就没有问题。但是如果选的值比较差,就会比较糟糕

c) 随机选取3个值,取中间值。这种方法对差值的风险抵抗能力比较强。一种常用的方法是选择数据的第一个值,中间的值,最后一个值。然后取这3个值得中间值。

代码片段:

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]);
	Swap(&A[Center],&A[Right-1]);
	return A[Right-1];
}

3)算法描述

这里,我们通过一个例子说明一下快速排序算法。

待排序数据为(8,34,51,21,18,64,26,32)首先利用上面的方法找到pivot为21,然后把pivot与A[N-1]=26交换位置。然后设定两个游标i,j。i向右滑动直到遇到大于pivot的值处停止,j向左滑动直到遇到小于pivot的值处停止,然后交换i,j对应的元素,然后继续上面的步骤知道i>j,然后交换i与pivot对应的元素。这样就把待排序数据集分成了两部分,然后递归调用上面的算法,最终得到排好序的数据。这里可能会有一个问题就是相等的元素,这将是一个特殊情形,例如数据中有几个值与pivot相等,那么当游标运动到了这几个位置时应该怎么办呢?游标继续向前走,越过这些值。


代码描述:

#define Cutoff (3)
void Qsort(ElementType A[], int Left, int Right)
{
	int i,j;
	ElementType pivot;
	if(Left + Cutoff <= Right)
	{
		pivot = Median3(A,Left,Right);
		i=Left;j=Right-2;
		for(::)
		{
			while(A[++i]<pivot){}
			while(A[--j]>pivot){}
			if(i<j)
				Swap(&A[i],&A[j])
			else
				break;
		}
		Swap(&A[i],&A[Right-2]);
		Qsort(A,Left,i-1);
		Qsort(A,i+1,Right);
	}
	else
		InsertionSort(A+Left,Right-Left+1);
}


void QuickSort(ElementType A[], int N)
{
	Qsort(A,0,N-1);
}

4)到底应该选取什么样的排序算法

我们已经介绍了几种排序方法,那么到底应该怎样选取排序方法呢?如果排序数目比较大,那么尽量用快速排序,如果数据量比较小,还是用插入排序或希尔排序比较好,因为这个两种方法比较简单,更重要的是在小数据量的排序中,快速排序的递归运算更加耗时。如果数据量相当大以至于无法完全在内存中运行,那么建议用归并排序,归并排序主要应用于外部排序中。当然还有一种桶排序,这个排序的速度相当迅速,但是限制条件太多,要求待排序数据为不大于某一值得正整数,约束性太强了。


5)排序方法的下界

任何只利用比较方法来排序的方法的最坏情况下需要


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值