快速排序模板
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N];
void quickSort(int l, int r){
if(l>=r) return;
int mid=a[l+r>>1];
int i=l-1, j=r+1;
while(i<j){
while(a[++i]<mid);
while(a[--j]>mid);
if(i<j) swap(a[i], a[j]);
}
quickSort(l,j);
quickSort(j+1,r);
}
int main(){
int n;
cin>>n;
for(int i=0; i<n; i++) cin>>a[i];
quickSort(0,n-1);
for(int i=0; i<n; i++) cout<<a[i]<<' ';
}
问题1 产生死循环
while(a[++i]<mid);
while(a[--j]>mid);
// 上面两行替换为下面两行,导致死循环问题
while(a[i]<mid) i++;
while(a[j]>mid) j--;
- 如果恰好出现 a[i]等于mid; a[j]等于mid的情况,下面的会产生死循环。
- 上面采用++i,--j的写法,相当于使用do-while循环,避免了死循环。配合 i=l-1, j=r+1使用
问题2 子递归的划分---死递归问题
- 死递归的原因是 (l,r)的递归空间,拆成了(l,l), (l,r)的空间,导致递归无法停止
- 两种划分方案
-
- quickSort(l,j); quickSort(j+1,r); 不会发生死递归
-
- quickSort(l,i-1); quickSort(i,r); 会发生死递归
- 分析可知,考虑参考轴的位置和边界的位置是否会重合?
- 如果重合时,是否会发生最后跳出循环后 (i,边界l, 参考轴 3者重合的情况);或 (j, 边界r, 参考轴 3者重合的情况)---这是死递归发生的根源
- 对于i划分,要避免l是参考轴,导致 i=l; 对于j划分,要避免r是参考轴导致 j=r; 由于 mid的选取为a[l+r>>1] 所以l~r只要有2个以上的数,参考轴不可能在r,也就不会死递归