快排简介

如果单纯要排序的话,可以用sort,归并也更加的好懂,但是快排有思想

可能是被C++养废了,我竟然不会快排了。

马上就要csp了。。。。

于是我想垂死挣扎一下。

ps:洛谷特别贴心的专门给了一道题作为快速排序的模板,题解里也有许多dalao的分享,并附带各种优化,蒟蒻我只会基础

首先快排的思想基于分治(它并没有严格意义上二分),每次选择一个基准点,那么这个数列就可以分成两部分,使得左部分的数都比这个基准数要小,而右边都要大(以升序排序为例),就像是一个分类。那么如果左右两边分别有序的话这就是一个有序的数列了对吧(这显然我们可以递归处理)。

那么问题的关键就是如何达到这种将数分类的效果。/讲真我觉得你瞎搞一顿弄出来了,也差不多就是快排了,毕竟原理其实差不多是吧。(小声bb)

看网上说有两种方法,一是挖坑法,二是交换法(??)。

挖坑法

以升序排列为例

这里假设基准点是最左端的数

这个坑呢开始也在基准数所在的位置(相当于把基准数取了出来)

维护两个指针l,r。

l从序列最左端开始,r从序列最右端开始

个人理解,l是在审判这些点中是否有>基准数的,r是在审判这些点中是否有<基准数的

毕竟l相对在左边,r相对在右边嘛。

轮流进行,先从r开始如果r所指的数比基准数小,就停下来,这个数是不合法的,它应该到左边去,去哪里呢?我们发现我们有一个坑,于是它就愉快的跑去了坑里。这时候这个数原来所在的位置就空了出来,于是这个位置就变成了了一个新的坑。并且这时l所指向的点就是这个被填了的坑,它肯定合法,所以l右移(我觉得不移也没有事)

现在该轮到l移动了,它也会找到一个不合法的数,这个数应该要到右边去,恰好此时坑又在右边,于是它就去填坑了,它的位置有变成坑,以此类推。

现在留下的问题是,什么时候结束呢?

注意到,每次一个指针在查找到一个不合法的数后,这个不合法的数转移了位置,轮到另一个指针行动,但是这个指针还在之前那个不合法的位置上。假如另一个指针找不到不合法的数不断向它靠近,就会遇到它,这说明两边都没有不合法的数了,且现在两个指针共同在的地方就是最后的一个坑,这是留给基准数的。把基准数填进去即可。

然后以基准数所在位置为分界点,递归分别操作

这么做为什么可以?

可以发现每次r发现有比基准数小的数时,会将它填入坑中,这个坑就是l所在的地方,它不会使得l前面出现不合法的。所以最终比基准数小的数一定在l的前面,并且l会将所有比基准数大的都弄走。r也是同理

在最后,我们将基准数填入了最终的坑中,这个坑是l,r相交的地方,那么它的左边就不可能有比基准数的的数,右边也不可能有比它小的数(上一段所述)。所以以这个位置为分界点,就是合法的。

总结一下流程

  1. 选定基准数,并设它所在位置为坑
  2. r指针左移,直到找到一个不合法的数,将这个数填到坑里去,并让这个数的位置为坑,l右移一格。或r遇到l停止
  3. l指针右移,直到找到一个不合法的数,将这个数填到坑里去,并让这个数的位置为坑,r左移一格。或l遇到r停止
  4. 若l,r相遇,则将基准数填到l,r相遇的位置上(也是最后剩下的一个坑)。否则就继续2,3
  5. 以基准数最后所处位置为分界点两边分别处理。

然鹅。。。

观察数据发现,给的是升序序列,成功被卡,正确性应该没问题。

快排优化在于基准数的选择,但是这种方法基准数一定要选第一个,所以只要随机选择一个数,让它和第一个数交换即可(妙啊)

Code:

#include <bits/stdc++.h>
using namespace std;
int n,a[100010];
void Quick_Sort(int L,int R)
{
	if (L>=R) return;
	int val=a[L];
	int l=L,r=R;
	while (l!=r)
	{
		while (r!=l&&a[r]>=val) r--;
		a[l]=a[r];
		while (l!=r&&a[l]<=val) l++;
		a[r]=a[l];
	}
	a[l]=val;
	Quick_Sort(L,l);
	Quick_Sort(l+1,R); 
}
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	  scanf("%d",&a[i]);
	Quick_Sort(1,n); 
	for (int i=1;i<=n;i++)
	  printf("%d ",a[i]);
	return 0;
}


我怎么写这么长。。。

交换法

随便选择一个基准数。

初始两个指针l,r分别区间最左端和最优端

先让l指针向右直到找到第一个大于基准数的数。再让r指针向左直到找到第一个小于基准数的数。

如果l小于等于r就将这两个指针所指的数交换,再让l++,r–

当l>r

我感觉要坑了…
但我还是发了出来

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值