目录
不多说我们先看快排是怎么写的
题目一
其实说白了这个排序直接调用内置函数sort()就可以做排序了,但我们还是分析以下快排的代码
帮助理解下一道题目
代码逻辑
难点就是理解做递归的这个过程
以 3 2 1 4 5 为例子
我是这样理解递归的
递归在我看来就是将原来的一个大的集合,拆分成小的集合,然后先对小集合操作,再对每个小集合进行合并
所以在看的时候是从小往大看的,即先对一个元素操作,再加入一个元素,每次操作完再加入一个元素
就像这里 我们是随便取一个序列中间的值x然后把比这个x小的数字放在x左边,比它大的放在右边
那么我们随便取一个元素
例如2 2就不需要操作 我们添加一个元素
(因为我对于一串数字而言 2 1 下标同时减去一个数字 相对顺序是不变的 不影响结果)
2 1 那么选组中间的那个数值x=q[0+1>>1]=2 0+1>>1 等价于0+1 除2
1比x小放到 进行操作完后的结果就是 1 2
那么我们再加入一个元素3
现在就是3 1 2
同样x=q[0+2>>1]=1
所以进行操作 1 3 2 此时x=3 继续操作 得到1 2 3
这样去想就会好理解很多
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100010;
int n; //表示数量
int q[N]; //存储数字序列
void quick_sort(int q[],int l,int r) //l表示左边界 r表示右边界
{
if(l>=r) return; //如果左边界大于等于右边界结束退出
int i=l-1,j=r+1,x=q[l+r>>1]; //i记录左边界 做移动 r记录有边界 做移动
while(i<j) // x表示中间的数值
{
do i++;while(q[i]<x); //如果左边的数小于x进行移动
do j--;while(q[j]>x); //如果右边的数大于x进行移动
if(i<j) swap(q[i],q[j]); //如果现在的左边界还小于右边界 进行交换
}
quick_sort(q,l,j); //递归求解
quick_sort(q,j+1,r);
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&q[i]);
quick_sort(q,0,n-1);
for(int i=0;i<n;i++) printf("%d ",q[i]);
return 0;
}
题目二
原理就是k是个下标
如果以新区间的左端点为起始位置, 形成一个新的k,区间内做个排序,指向的依然是我要找的q[k]
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100010;
int q[N];
int n,k;
int quick_sort(int l,int r,int k)
{
if(l>=r) return q[l]; //返回第一个大于等于x的数字
int i=l-1,j=r+1,x=q[l+r>>1];
while(i<j)
{
do i++;while(q[i]<x);
do j--;while(q[j]>x);
if(i<j) swap(q[i],q[j]);
}
int s=j-l+1; //这里用来判断k在那一部分里 用来减少计算
if(k<=s) return quick_sort(l,j,k);
else return quick_sort(j+1,r,k-s);
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++) scanf("%d",&q[i]);
cout<<quick_sort(0,n-1,k);
}
题目来源acwing
模板来源:闫学灿
链接:https://www.acwing.com/activity/content/code/content/57785/
来源:AcWing