排序
Ⅰ. 排序
一. quicksort
1. 手敲
注释版
点击查看代码
void quicksort(int q[],int l,int r){
//递归终止的情况
if(l>=r)return;
//子问题处理
int mid=q[l+r>>1],i=l-1,j=r+1; //quicksort中的mid为数而不是下标
//>>1速度比/2更快 //取中值比取随机值更快,且能防止因为边界问题导致死循环
while(i<j){ //不需要=,i==j便停止
do i++;while(q[i]<mid); //=mid时也停止可以有效防止越界(需要理解这点)
do j--;while(q[j]>mid); //该操作使i,j交点处左边的数均小于mid,右边的数均大于mid
if(i<j)swap(a[i],a[j]); //大于等于时不用交换
}
//递归处理子问题
quicksort(q,l,j),quicksort(q,j+1,r); //i不一定==j
}
//注l,r相邻时,意qsort(l,r)不能分治为qsort(l,r)否则会死循环
//(l+r)>>1 =l
//quicksort(q,l,l),quicksort(q,r,r); //正确
//quicksort(q,l,i),quicksort(q,i+1,r); --> quicksort(q,l,r),quicksort(q,r+1,r);错误
简洁版
点击查看代码
void qsort1(int a[],int l,int r){
if(l >= r)return ;
int mid = a[l + r >> 1],i = l - 1, j = r + 1; //int mid = a[l + r + 1>> 1]
while(i < j){
do i ++;while(a[i] < mid);
do j --;while(a[j] > mid);
if(i < j)swap(a[i],a[j]);
}
qsort1(a,l,j),qsort1(a,j + 1,r); //qsort1(a,l,i),qsort1(a,i + 1,r);
}"排序后(从小到大)"
void qsort2(int a[],int l,int r){
if(l >= r)return ;
int mid = a[l + r >> 1],i = l - 1, j = r + 1;
while(i < j){
do i ++;while(a[i] > mid); //符号相反
do j --;while(a[j] < mid);
if(i < j)swap(a[i],a[j]);
}
qsort2(a,l,j),qsort2(a,j + 1,r);
}"排序后(从小到大)"
bool cmp(int a,int b){
return a > b;
}
"排序后(从小到大): " sort(a,a+n); //qsort1(a,a,n);
"排序后(从小到大): " sort(a,a+n,cmp); //qsort2(a,a,n);
总结快排思路
-
有数组
, 左端点 , 右端点 -
确定划分边界
-
将
分为 和 的两个小数组 的含义: 之前的元素都 , 即 的含义: 之后的元素都 , 即结论: while 循环结束后,
简单不严谨证明
while 循环结束时,
若 , 显然成立若
∵ 最后一轮循环中两个 do−while 循环条件都不成立
∴
∴
∴ 结论成立
-
递归处理两个小数组
2. sort
二. mergesort
点击查看代码
void mergesort(int q[],int l,int r){
//递归的终止情况
if(l>=r)return; //相等就不用再排序啦
//第一步:分成子问题
int mid=l+r>>1;
//第二步:递归处理子问题
mergesort(q,l,mid),mergesort(q,mid+1,r); //分治
//第三步:合并子问题
int k=0,i=l,j=mid+1;
while(i<=mid&&j<=r){ //=压入最后一个元素
if(q[i]<=q[j])temp[k++]=q[i++]; //一般第一短优先,大于时从大到小排序,小于号时从小到大排序
else temp[k++]=a[j++];
}
while(i<=mid)temp[k++]=q[i++];
while(j<=r)temp[k++]=q[j++]; //另一端末端
for(int i=l,k=0;i<=r;i++)q[i]=temp[k++]; //返回原数组
}
//注意temp如果在函数中定义的话不要t[N]
总结归并思路
-
有数组
, 左端点 , 右端点 -
确定划分边界
-
递归处理子问题
-
合并子问题
① 主体合并
至少有一个小数组添加到
数组中② 收尾
可能存在的剩下的一个小数组的尾部直接添加到
数组中③ 复制回来
数组覆盖原数组
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】