最开始我们学习编程,首先接触的排序算法应该都是冒泡排序,虽然这种算法代码量少且较好理解,但其时间复杂度相对较高,在面对大数据时代码运行速度明显变慢,因此今天我们来介绍一种冒泡排序的改进算法——快速排序
该算法的实现主要基于以下几个步骤:
1:在待排序的数组中取一个基准数(可随机取,但通常为数组两端点或中间的数)
2:将数组中的数逐个与基准数比较,较大的置于基准数右侧,较小的置于基准数左侧
3:对基准数两侧数组不断重复上述两个步骤,直到每个子集只有一个元素即为全部有序(此处可用函数的递归实现)
下面以一道acwing上的模板题为例子进行讲解
这里附上原题链接: 785. 快速排序 - AcWing题库
那我这里就以输入样例来简单分析一下算法的实现
1:首先取基准数,那这里我们选取数组中间的2为例
2:创建两个指针i,j,i指向数组左边界偏移1,j指向数组右边界偏移1(这里后面会解释,用到了do while循环),当i指向的数小于基准数时继续右移,直到遇到不比基准数小的数时停止,此时开始将j左移,直到遇到不比基准数大的数时停止。此时两个指针都已移动完毕,用swap函数交换两指针的位置
3:第一次排序完毕后,递归调用函数,对基准数的左边子区间和右边子区间进行上述两步骤排序,直至数组有序(即区间内只有一个元素)
下面我们以图解的方式帮助大家理解
首先确定基准数
然后按照上述所讲将i,j进行移动(因为i已满足条件所以此次不移动)
交换i,j所指元素,此时第一次排序已完成,开始下一次递归(注意此时基准数右侧已有序故右侧递归无实际意义,我们只讲左侧的递归)
此次根据之前所讲将1作为基准数,而此时i,j指针均已经满足条件停止,接下来进行交换
可以看到此时数组已经全部排序完毕,函数执行完毕
下面给出快速排序的模板供大家参考
void quick_sort(int q[], int l, int r)
{
if (l = r) return;//如果只有一个数据便直接结束
int i = l - 1;
int j = r + 1;//因为这里使用了 do while循环所以要将l和r分别偏移1代码运行时才指向数组的实际边界
int x = q[(l+r+1)/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);
}
本题完整代码
#include<iostream>
#include<cmath>
using namespace std;
const int N = 1e6 + 10;
int n; int q[N];
void quick_sort(int q[], int l, int r)
{
if (l == r) return;
int x = q[(l + r + 1) / 2];
int i = l - 1;
int j = 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]);
}
}
quick_sort(q, l, i - 1);
quick_sort(q, i, r);
}
int main()
{
int n = 0;
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;
}