基础算法之快速排序(quick_sort)

  最开始我们学习编程,首先接触的排序算法应该都是冒泡排序,虽然这种算法代码量少且较好理解,但其时间复杂度相对较高,在面对大数据时代码运行速度明显变慢,因此今天我们来介绍一种冒泡排序的改进算法——快速排序

  该算法的实现主要基于以下几个步骤:

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;
}

 

 

 

 

 

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值