AcWing 785. 快速排序 题解

原题链接:ACWing 785. 快速排序.

题目描述

给定你一个长度为n的整数数列。

请你使用快速排序对这个数列按照从小到大进行排序。

并将排好序的数列按顺序输出。

输入格式

输入共两行,第一行包含整数 n。

第二行包含 n 个整数(所有整数均在1~109范围内),表示整个数列。

输出格式

输出共一行,包含 n 个整数,表示排好序的数列。

数据范围

1 n 100000 1 \leq n \leq 100000

输入样例:

5
3 1 2 4 5

输出样例:

1 2 3 4 5

题目分析

本题是一道基础算法的模板题,考察的就是快速排序。

快速排序是一种基于分治的算法,基本步骤为:

  1. 确定分界点 pivot
    在区间[left, right ]内选择分界点的方式一般有
    ①num[left]
    ②num[right]
    ③ num[left+right>>1] (也就是取中间元素)
    ④num[rand()%len] (随机取点)
    本题中选用方式①和②作为pivot会被卡掉

  2. 将大于等于pivot的元素移到右边,小于等于pivot的元素移到左边(但是pivot不一定归位)。
    调整的方式其实是一种双指针算法
    每次左指针i寻找≥pivot的元素,右指针j寻找≤pivot的元素
    if i<j则交换num[i], num[j]
    当i ≥ j时说明已经调整完毕

  3. 递归处理由pivot划分的左右区间。
    递归终止条件:区间内只有一个元素即left ≥ right时结束。

算法分析

时间复杂度:平均情况O(nlog2n), 最坏情况O(n2)

算法实现

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 1e5+10;
int num[N];

void quick_sort(int l, int r) {
    if(l >= r) return;//只有一个元素或无元素递归结束
    int pivot = num[l+r>>1];//取中间元素作为枢轴
    //利用双指针算法划分区间
    int i = l-1, j = r+1;
    while(i < j) {
        while(num[++i] < pivot);
        while(num[--j] > pivot);
        if(i < j) swap(num[i], num[j]);
    }
    //递归排序子区间
    quick_sort(l, j);
    quick_sort(j+1, r);
}

int main() {
    int n;
    scanf("%d", &n);
    for(int i = 0; i < n; ++i) scanf("%d", &num[i]);
    
    quick_sort(0, n-1);
    
    for(int i = 0; i < n; ++i) printf("%d ", num[i]);
    puts("");
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/mwl000000/article/details/108133170