重温经典:快速排序

快速排序(quick sorting)又称为划分排序。快速排序是对气泡排序的一种改进,在气泡排序中,进行元素的比较和交换式是在相邻的单元中进行,每次只能前移或者后移一个位置,因而总的比较和移动次数较多。在快速排序中,记录的比较和交换是从两端向中间进行,较大的元素一次就可以交换到后面。

快速排序的过程可以叙述为:首先从待排序区间(A[0]~A[n-1])中选取一个元素(一般选取该区间第一个元素)作为比较的基准元素,通过从区间两端向中间顺序比较进行比较和交换,使前面单元中只保留比基准元素小的元素,后面单元只保留比基准元素大的元素,而把每次在前面单元中碰到的比基准元素大的元素同在后面单元中碰到的小于基准元素的元素交换其值。当所有元素都比较一遍后,把基准元素交换到前后两部分的交界处,这样前面单元内的元素都小于等于基准元素,后面的单元内的元素都大于等于基准元素。然后对前后两个区间分别重复执行上述过程,当一个区间为空或者只包含一个元素时,就结束排序。

在快速排序中,把待排序的区间按照第1个元素(基准元素)分成前后两个区间,假设区间是A[s]~A[t],设置x=A[s],从i=s+1开始,依次向后取值,并使每一个A [i]和X比较,当碰到A[i] >X或者i>j时,再让j从t开始,依次向前取值,并使每一个A[j]和x比较,当碰到A[j] <X或者j<i时止,如果i<j则交换A[i] 和A[j],然后继续让i向后取值重复上面步骤,直到i>j位置。此时,A[s]~A[j]区间的元素都是小于等于基准元素A[s], 而A[i]~A[t]区间的元素都是大于等于基准元素A[s]的,i=j+1,最后把A[s] 和A[j]交换值,A[j]就是固定后的值,至此就完成了一次区间划分,得到了两个区间A[s]~A[j-1]  A[j+1]~A[t],在这两个区间内分别执行上述步骤,就可以得到最终的排序结果。

例如有10个元素:{35、10、17、40、39、9、50、44、16、26}

进行一次数据划分的过程如下:

                                         

因为在快速排序法中存在着不相邻元素之间的交换,所以快速排序也是一种不稳定的排序方法。快速排序中,如果把每次所用的基准节点看做是树根,把划分出的前后区间看做是根节点的左右子树,那么整个排序过程就对应着一颗具有n个元素的二叉搜索树,所需要划分的所有区间数就等于对应二叉树搜索树中的分支节点数,例如上面找到35节点将元素分成两个区间可看成是以35为根节点的二叉搜索树:

                                               

因为通常是取第一个元素做为基准元素,所以就会存在一种情况,第一个元素并不能很均衡的把所有元素均匀分成两个区间,为了避免快速排序最差情况的发生,一是若事先知道待排序的元素基本有序是可以选择其他排序方法,二是修改选择基准元素的方法使得在每次划分之前比较当前区间第一个元素、中间元素、最后一个元素,从这三者中选取居中的一个元素做为基准元素。

void QuickSort(int *A,int s,int t)
{
    int i =s+1;
	int j =t;
	int x =A[s];
	while(i<=j)
	{
	    while(A[i]<=x && i<=j)i++;  //i向后移动
		while(A[j]>=x && j>=i)j--;  //j后前移动
		if (i<j)
		{
		    int tmp =A[i];
		    A[i]=A[j];
			A[j]=tmp;
			i++;
			j--;
		}
	}
	if(s!=j)
	{
	    A[s]=A[j];
		A[j]=x;
	}
	if(s<j-1)
	{
	    QuickSort(A,s,j-1);
	}
	if(j+1<t)
	{
	     QuickSort(A,j+1,t);
	}
}

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值