经典排序算法之快速排序详解

 写在前面:大家好!我是ACfun,我的昵称来自两个单词Acceptedfun。我是一个热爱ACM的蒟蒻。这篇博客来记录一下快速排序算法以及快速排序的模板。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正,感谢大家的不吝赐教。我的唯一博客更新地址是:https://ac-fun.blog.csdn.net/。非常感谢大家的支持。一起加油,冲鸭!
用知识改变命运,用知识成就未来!加油 (ง •̀o•́)ง (ง •̀o•́)ง

快速排序简介

快速排序是对冒泡排序的一种改进。冒泡排序的时间复杂度为O(N²),这是一个非常高的时间复杂度。冒泡排序早在 1956 年就有人开始研究,之后有很多人都尝试过对冒泡排序进行改进,但结果却令人失望。如 Donald E. Knuth(中文名为高德纳,1974 年图灵奖获得者)所说:“冒泡排序除了它迷人的名字和导致了某些有趣的理论问题这一事实之外,似乎没有什么值得推荐的。”
 快速排序之所以比较快,是因为相比冒泡排序,快速排序每次交换是跳跃式的每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样只能在相邻的数之间进行交换,交换的距离就大得多了。因此总的比较和交换次数就少了,速度自然就提高了。当然在最坏的情况下,仍可能是相邻的两个数进行了交换。因此快速排序的最差时间复杂度和冒泡排序是一样的,都是 O(N²),它的平均时间复杂度为 O(NlogN)
快速排序动画演示:
快速排序

快速排序的思想

 快速排序的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分关键字都比另一部分记录的关键字小,然后再分别对这两部分关键字进行相同步骤的排序,直到整个序列有序。

快速排序的具体实现

 一趟快速排序的具体做法是:附设两个变量lowhigh,分别指向第一个数据和最后一个数据。首先从low所指的位置向后找到第一个关键字大于监视哨的值,然后high开始向前移动直到找到第一个小于监视哨的值,然后将两个数据位置交换。现在我们将下面这一串数据进行快速排序:

6 1 2 7 5 3 4 9 10 8

1.将数字 5 设置为监视哨[ (low + high) / 2 ],然后开始第一轮的快速排序。
2.首先从low就是数据的最左端寻找到第一个比 5 大的值 6 ,然后从high就是最右端寻找到第一个比 5 小的数字4。然后将这两个数字交换位置:
41 2 7 5 3 6 9 10 8。
3.然后low继续向后移动直到找到第二个比 5 大的数据 7 ,high继续向前移动找到第二个比 5 小的数字 3,然后将两者位置交换:
4 1 2 3 5 7 6 9 10 8。
 此时我们发现 5 左边的数据全部比 5 小,右边的数据全部比 5 大。即将数据以 5 为界将数据分为了两个部分。然后我们分别对这两部分分别执行相同的操作。此时左边的数据为“4 1 2 3 5”,右边的数据为“7 6 9 10 8”。然后分别使用递归处理这两个部分。依次进行上述操作直到整个序列变得有序。

快速排序模板

void quick_sort(int q[],int l,int r){
    
    if(l >= r) return;
    int x = q[(l + r) >> 1], i = l - 1, 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, j);
    quick_sort(q, j + 1, r);
}

例题

题目信息

原题链接:快速排序

题目描述

 给定你一个长度为n的整数数列。请你使用快速排序对这个数列按照从小到大进行排序。并将排好序的数列按顺序输出。

输入格式

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

输出格式

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

数据范围

 1≤n≤100000

输入样例:

 5
 3 1 2 4 5

输出样例:

 1 2 3 4 5

解题代码

#include<iostream>
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], i = l - 1, 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, 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]);
    }
    
    return 0;
}

注意:这里没有使用 cin>> 和 cout<< 的原因是其输入输出速度不如 scanf() 和 printf() 快,所以在这里使用的是 scanf() 和 prinf() 。


我是ACfun,感谢大家的支持!
上号

猜你喜欢

转载自blog.csdn.net/qq_41575507/article/details/107271279