经典排序算法6——快速排序

快速排序对给定数组中的元素 进行重新排列,以得到一个快速排序的分区,在一 个分区中,所有在s下标之前的元素都小于等于A[s],所有在s下标之后的元素都大于等于A[s],即A[s]已经位于它在有序数组中的最终 位置。

1.首先选择一个元素为中轴,一般选择为第一个元素, A[l]

2.建立分区:分别扫描与中轴比较,一次从左到右(用i表示)直到遇到第一个大于中轴的元素,另一次从右到左(用j表示)直到遇到第一个小于等于中轴的元素

3.两次扫描全部停止会发生3种不同的情况

  1)扫描指针i,j不相交,即i<j,交换A[i]和A[j],再分别对i+1,j-1,然后继续进行扫描

  2)扫描指针相交, 即i>j,把中轴和A[j]交换以后,得到该数组的一个分区

    j\leftarrow \rightarrowi  
p 全部\leqslantp \leqslantp \geqslantp 全部\geqslantp

3)扫描指针指向同一个元素,也就是i=j,被指向的元素一定等于p,建立该数组的一个分区,分裂点的 位置S=i=j。

    \rightarrowi=j\leftarrow  
p 全部\leqslantp =p 全部\geqslantp

合并后两种情况,只要i\geqslantj,就交换中轴和A[j]的位置。

注意:在这种形式下,下标i可能会超过子数组的边界

如果所有的分裂点位于相应子数组的中点,就是最优情况,键值的比较次数:C_{best}(n)=nlog_{2}n

在最差情况下,所有的分裂点都趋于极端:两个子数组有一个为空,而另一个子数组仅仅被分区数组少一 

个元素,这会在已 排好序的情况下出现,键值的比较次数:

C_{worst}(n)=(n+1)+n+...+3=\frac{(n+1)(n+2)}{2}-3\in \Theta (n^{2})

平均情况下,当n>1时,C_{avg}(n)=\frac{1}{n}\sum_{s=0}^{n-1}[(n+1)+C_{avg}(s)+C_{avg}(n-1-s)]\approx 2n \cdot ln\cdot n\approx 1.38nlog_{2}\cdot n

因此在平均情况下,仅比最优情况下多执行38%的比较操作,其最内 层循环效率非常高,使得在处理随机排列的数组时,速度要比合并排序快。

void QuickSort(int a[],int l,int r)
{
	
	if (l<r)
	{
		int i=l,j=r,key=a[l];
		while(i<j)
		{

			while(i<j && a[j]>=key)
				j--;
			if (i<j)
			{
				a[i++] = a[j];
			}
			while(i<j && a[i]<key)
				i++;
			if (i<j)
			{
				a[j--] = a[i];
			}
			
		}
		a[i]=key;
		QuickSort(a,l,i-1);
		QuickSort(a,i+1,r);
	}
	return;
}

猜你喜欢

转载自blog.csdn.net/zxycele/article/details/81512451