排序算法之快排

一.思想简介:

快排也是用到分治的思想,将问题分层次解决。总体思想就是拿出一个该列表的数,将所有小于等于这个数的数都放在它的左边,所有大于等于它的数都放在右边,那么这个数的位置就确定了。至于怎么实现很巧妙,和想法有些不同。是先找到位置,再将该数放到那个位置上的。

1.拿到一个序列:

(1)我们将第一个数(人为设定,方便求解)规定为中间数;

(2)从右往左找第一个比它小的数 ,然后再从左往右找第一个比它大的数,交换两数;

(3)再继续此过程,直到两个数重合,此时该位置左边应全小于等于中间数,该位置右边应全大于等于中间数。此时我们将中间数放到这个位置上,也就是交换该位置的数和第一个位置的数,则中间数的位置就排好了(整个数列有序后它在的位置就是这个位置),接下来只要分别排该数两边的序列就好了;

(4)分别将该数两边的序列进行以上方法的排序,可以用递归来实现。那么就差递归的退出条件啦,当该序列只有一个元素(l = r)时,可以看作有序,即递归结束。

2.细节考虑:

(1)开始一直再考虑,从左右两边找数的时候,等于的情况用不用单独分析,后来觉得没必要分析,等于既可以放到右边也可以放到左边,所以就不考虑等于了,直接找小于或大于。

(2)有一个重点,要先从<——这个方向找小于的数,再从——>这个方向找大于的数。

         为什么呢?因为我们得到的中间位置(i = j 的位置)的数要和第一个位置的数做交换,而第一个位置处于左边,最后这个地方的数一定是小于等于中间数的。在最后一次找数时,i 位置的数小于等于中间数,j 位置的数大于等于中间数,如果先——>这个方向找小于值,结果找不到,和 j 上面的数重合了,于是会将 j 位置当作中间位置,将该数与第一个数做交换,结果第一个数大于等于中间数,大于时就背离了我们的初衷了。同理可得,按我们规定的正确顺序,第一个数结果小于等于中间数的,满足我们的要求。

(3)按两个方向找数时,当 i >= j 时也要退出了。

二.代码实现

#include <iostream>
#include <vector>
using namespace std;

vector<int> a = { 2,5,5,5,2,1,4,4,3,1 };

// 传入带排序列的最左和最右下标 
void qsort(int l, int r)
{
	if(l >= r)         // 循环退出条件,序列中只有一个数,认为有序,不用排了 
	  return;
	int i = l,j = r;   // 初始化 i,j; 
	while (i < j)      // 当中间位置还没有出现时 
	{
		for (j; a[j] >= a[l] && i < j; j--);   // <—方向找小于值  注意要加 i < j 
		for (i; a[i] <= a[l] && i < j; i++);   // —>方向找大于值 
		if (i != j) swap(a[i], a[j]);          // 交换两值,为了使左边为小于值,右边为大于值 
	}
	swap(a[l],a[i]);      //交换中间位置值和第一个位置值 
	qsort(l, i - 1);       //排序前边的列表 
	qsort(i + 1, r);       //排序后边的列表 
}

int main()
{
	qsort(0, a.size() - 1); 
	for (auto i : a)
		cout << i << " ";
	return 0;
}

over!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值