排序算法之快速排序

基本思想:

(1)在待排序的序列中随便找一个数作为基准数(用来参照的数),假设将第一个数作为基准数,接下来,需要将这个序列中所有比基准数大的数放在它的右边,比基准数小 的 数放在它的左边。

(2)目标是将基准数挪到序列中间的某个位置,假设这个位置是k。现在就需要寻找这个k,并且以第k位为分界点,左边的数都小于等于基准值,右边的数都大于等于基准值。

(3)如何找到位置k:我们采用从序列的两端向中间扫描的方法,假设  i 指向左端的第一个数,j 指向右端第一个数(最后一个数)。每次进行扫描时,先让 j 移动,当扫描到小于基准数的时候,i 开始移动,直至找到大于基准数,将这俩个数值进行交换,j 和 i 继续扫描,交换,直至 i 和 j 相遇,说明第一轮扫描结束,将该位置与基准数交换,这样基准数的左边全是小于它,基准数的右边全是大于它。

问题:为什么是右边 j 先进行扫描? (先思考,后面有解释)

(4)这样以k 位置分出俩个序列,左边是小于基准数的序列,右边是大于基准数的序列。我们再通过(1),(2)和(3)步骤对俩个序列进行排序,以此类推,直至再也分不出子序列为止。

template<class T>
void list<T>::quicksort(int low,int high)
{
	if (low < high)
	{
		int pos = Arrayadjust(low,high);  //返回调整后的基准数的位置
		quicksort(0,pos - 1);//对右区域进行排序
		quicksort(pos + 1, high); //对左区域进行排序
	}
}

方法一:

数值交换法:

template<class T>
int list<T>::Arrayadjust(int low, int high) //区间的排序
{
	node<T> x = vec[low]; 
	int xx = low; //保存基准位置
	while (low < high)
	{
		while (low<high&&vec[high].data >= x.data) //从右到左寻找小于基准的数
			--high;

		while (low<high&& x.data >= vec[low].data)//从左到右寻找大于基准的数
			++low;

		if (low < high)
		{
			T dt = vec[high].data;
			vec[high].data = vec[low].data;
			vec[low].data = dt;
			--high;
			++low;
		}
	}

	T tp = vec[high].data;   //交换基准值
	vec[high].data = x.data;
	vec[xx].data = tp;

	return high;
}

这种方法是对序列的值进行互相交换,左边查找大于基准的数,右边查找小于基准的数。当找到k位置时候,与基准的值进行交换。


方法二:

挖坑法:

template<class T>
int list<T>::Arrayadjust(int low,int high) //区间的排序
{
	node<T> x = vec[low]; //基准位置
	while (low < high)
	{
		while (vec[high].data > x.data) //从右到左寻找小于基准的数
			--high;
		if (low < high)
		{
			vec[low].data = vec[high].data;
			++low;
		}
		while (low<high&&vec[low].data<x.data)//从左到右寻找大于基准的数
		{
			++low;
		}
		if (low < high)
		{
			vec[high].data = vec[low].data;
			--high;
		}
	}
	vec[low].data = x.data;

	return low;
}


这俩种方法是参考下面博客的思路:

1.http://developer.51cto.com/art/201403/430986.htm

2.http://blog.csdn.net/morewindows/article/details/6684558


问题答案:如果是左边先扫描,在定位K位置时,很有可能将大于基准的值交换到左边,造成排序失败,因为左边扫描时只有在遇到大于基准值才停止。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值