快排的思想是基于 分治 思想的一种排序方法,核心思路分为以下几步:
① 确定 左右边界 l 和 r
② 设置x,值可以是q[l] , q[r] 或者q[(l + r) / 2]
③ 递归排序左右区间
我们可能并不清楚x到底在待排数组的哪个位置,但是我们基于一种 抽象 的思想。
我不管x在哪里,我就分成两块
#includeusing namespace std;const int N = 1e9 + 8;
int n ;
int q[N];void quick_sort(int q[] , int l , int r){if(l >= r ) return;int i = l - 1 , j = r + 1 , x = q[l + (r - l) / 2] ;while(i < j ){do i ++; while(q[i] < x);do j --;while(q[j] > 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]);}
}
输入
首先使用scanf进行输入,在如果数字较大的情况下scanf的效率比cin效率高
快速排序
整体是基于 分治 + 递归 实现的排序,所以首先定义边界出口
if(l >= r)
当然,这里可以直接写成 ==,但是出于习惯我还是写成了>=,因为其他的一些题目并不是++,所以并不一定相等,而且>= 包含了 == 的情况
循环条件
while(i < j)
这里这样写的原因是因为,我们使用的是 双指针 , 所以可能出现交叉的情况,但是我们并不需要让他们交叉
如果出现了交叉的情况,那么就说明 i当前指的位置是大于X的数,j指的数是小于X的数,我们进行交换就可以得到一个比较有序的情况。
循环体
通过指针i,我们要找到 > x的数
通过指针j,要找到< x的数
这里需要注意的是,由于
do-while循环的特殊性所以对于i 和 j的取值就有讲究了,
i = l - 1j = r + 1因为do-while首先就会无条件的执行一次,所以需要让i 和 j到边界外面去
然后判断i < j,因为在这中间可能出现 i 并不满足小于j的情况——循环结束条件
if(i < j)
所以需要进行判断。
递归执行
前一步已经通过双指针完成了区间的划分,现在需要将两个区间进行 递归排序
quick_sort(q , l , j);
quick_sort(q , j + 1 , r);
AcWing 785. 快速排序 - AcWing