快速排序【算法解析,代码模板】

快排的思想是基于 分治 思想的一种排序方法,核心思路分为以下几步:

① 确定 左右边界 l 和 r

② 设置x,值可以是q[l] , q[r] 或者q[(l + r) / 2]

③ 递归排序左右区间

我们可能并不清楚x到底在待排数组的哪个位置,但是我们基于一种 抽象 的思想。

我不管x在哪里,我就分成两块

  • 左边的一块,全部小于 X
  • 右边的一块,全部大于 X

代码模板

#include

using 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 - 1
  • j = 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

你可能感兴趣的:(PTA,算法,c++,数据结构)