【0基础学算法】快速排序(超详细讲解+私人笔记+源码)上

简介: 笔记

前言:


大家好,这是0基础学算法的第一课,当然这个0基础并不是我们常规意义上的0基础,你需要掌握一点语法知识即可学习此课程,夸张点说会敲“Hello World”就行/doge。当然这是一个系列课,我将由简到深的为大家讲解一些算法知识,从排序到搜索以及更多,也希望这个系列可以给你带来帮助。算法学习是个很难的过程,希望你可以在此过程中坚持下来,加油!


附:系列中出现较难的知识点或者语法知识我都会作讲解,如果还有什么不明白的知识可以在下方评论,本人看到后会立即回复滴。


知识讲解:


下面直接开始我们今天所要讲解的知识——快速排序。


快速排序重要性:

快速排序是我们在编程技术中十分常见的一种排序方式,其由于排序效率在同为O(N*logN)的几种排序方法中效率较高,所以经常会被采用,再加上处理快速排序时使用的分治法思想十分实用,这就导致了很多的软件公司(腾讯,微软等知名IT公司)在笔试面试的时候也会很喜欢考这个,还有我们在程序方面的考试(软考等)和一些比赛(PAT,蓝桥杯等)还有考研中都会经常出现他的身影。


快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。我们在实现快速排序的时候会采用一种分治的策略,也成为分治法(Divide-and-ConquerMethod)。


分治法的基本思想:

分治法可以通俗的解释为:把一片领土分解,分解为若干块小部分,然后一块块地占领征服,被分解的可以是不同的政治派别或是其他什么,然后让他们彼此异化。


实现步骤:

在我们今天学习的算法中,我们将其分为以下的三个步骤:


1.先从数列中取出一个数作为基准数。(确认边界点)

2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。(重新调整区间)

3.再对左右区间重复第二步,直到各区间只有一个数。(递归)

看完上面你也不妨看出我将其简化为:确认边界点-重新调整区间-进行递归。三个步骤去进行实现。在这三个步骤中,要注意的一点是:在进行确认边界点的时候我们要考虑确定的边界点是左边界?右边界?中点?随机?的同时也要考虑取哪个点更方便我们后续的操作。

5.png


如上文所说,我们在分区选点的时候会面临着四种选择,在这里我们选择取中间点为我们的分界点,在这里会有人问为什么不取其他的点呢,先说随机点,这个就相对来说比较麻烦,然后左右两个端点为什么不建议取呢,主要是左右两个端点与后面开区间时会有边界值无法通过的现象,我们在举出特殊例子时是可以看出的,在这里我就不为大家列举了,这个知识相对来说没那么重要,我们只需记得取中间点为分界点即可。


在经过第一步的思考后我们在进行分区的操作是也如下图所示:


6.png

快速排序分区过程实现简图

到这里我们距离实现快速排序也只差了一步,也就是我们的递归,这个递归就是我们就是不断分界,分到最小单元。(当然这个现在看不懂没关系,到后面的代码展示环节时会出现)


举例:

我为大家举一个实例来帮助大家理解。以一个数组作为示例,取区间中间数数为基准数(标红)。


数组7.png

然后我们将左右两个端点的下标记住,

8.png


之后的我们就将左右两个元素交换,交换后继续重复上述操作,直到两个指针相遇停止,也就是如下操作:

交换位置:9.png

之后继续移动直到相遇:

10.png

相遇的时候对应下标为:4 。这个时候明显可见我们数组中0-4的数字都是<=85的,而5-9的数字都是>85的。


所以我们就将数组一分为二(并不是真正意义上的分开),0-4分开进行排序,5-9分开进行排序。


排序的过程也就跟我们上面所描述的一样。


数组

0 1 2 3 4 5 6 7 8 9

82 24 73 71 85 94 88 90 86 93

相信聪明的各位已经看出来了,这里的一分为二就是在同一个数组上分开两次进行上述方法的交换。交换的具体过程我就不细写啦,结果如下:


数组

0 1 2 3 4 5 6 7 8 9

71 24 73 82 85 86 88 90 94 93

然后继续套娃,分开进行:


数组

0 1 2 3 4 5 6 7 8 9

71 24 73 82 85 86 88 90 94 93

数组

0 1 2 3 4 5 6 7 8 9

24 71 73 82 85 86 88 90 93 94

显而易见到这里我们的排序就完成啦,也成功的对这个数组进行了一次排序。


思路:

思路就是对上面步骤以及例子的总结。我之所以放到例子后面附上主要是希望大家通过看例子可以加深对这些的记忆。在这里我直接为大家附上图,希望大家更容易理解一些。


思路一:

思路一就是我们的暴力解法,直接开两个数组,然后找出分界点,将比分界点小以及大的数字分别放入两个数组,最后再归还为原数组。

11.png



思路二:

在这里思路二也就是我们上面举例子用的方法,也是我们今天主讲的思路,就是用双指针进行不断靠近。



快速排序实现:

在这里快速排序的实现我就为大家简化为下面几步:


第一步:开一个数组


第二步:输入元素个数


第三步:将每个元素输入


第四步:调用模板


非常的通俗易懂是吧,在这里大家都想知道这个模板是什么,所以我们的重头戏就来了!

模板:

模板的实现我给大家已画图的方式列出,字丑希望大家不要介意。


14.png


在这里你可能会疑惑,哎?这不就是刚才讲的那些内容吗,为什么还要再说一遍呢?


我之所以在这里再提到一遍,主要是因为在我们学算法刷题时,不是说只学那个方法就可以了,我们有很多要考虑的东西,有的边缘值了,范围了都需要我们考虑。就比如刚才模板中的1个数不用排序的情况,如果我只给你讲解了前面的知识,你可能会理解快速排序,但是你自己实现起来会有很大的难度,有很多是你很难想象的到的错误,所以大家不要嫌我讲的繁琐。/抱拳


模板的代码实现:

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


好了,到了这里肯定有hxd会问:l+r>>1是什么意思。我在这直接为大家讲一下:


这里>> 就是二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。


简单点来说 x>>1等价于x/2 。


为了方便大家学习,我直接把这两个公式给大家附上,希望大家可以看一下:


·        x >> n 等同于 x / (2^n)  ,x << n 等同于 x * (2^n)


实战

到这里大家对快速排序已经了解的差不多了,下面看几个简单的题目来巩固一下吧。





相关文章
|
12天前
|
搜索推荐 C语言
【排序算法】快速排序升级版--三路快排详解 + 实现(c语言)
本文介绍了快速排序的升级版——三路快排。传统快速排序在处理大量相同元素时效率较低,而三路快排通过将数组分为三部分(小于、等于、大于基准值)来优化这一问题。文章详细讲解了三路快排的实现步骤,并提供了完整的代码示例。
39 4
|
14天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
56 8
|
14天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
47 7
|
1月前
|
算法 API 计算机视觉
人脸识别笔记(一):通过yuface调包(参数量54K更快更小更准的算法) 来实现人脸识别
本文介绍了YuNet系列人脸检测算法的优化和使用,包括YuNet-s和YuNet-n,以及通过yuface库和onnx在不同场景下实现人脸检测的方法。
49 1
|
1月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
64 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
1月前
|
算法
❤️算法笔记❤️-(每日一刷-160、相交链表)
❤️算法笔记❤️-(每日一刷-160、相交链表)
18 1
|
1月前
|
数据可视化 搜索推荐 Python
Leecode 刷题笔记之可视化六大排序算法:冒泡、快速、归并、插入、选择、桶排序
这篇文章是关于LeetCode刷题笔记,主要介绍了六大排序算法(冒泡、快速、归并、插入、选择、桶排序)的Python实现及其可视化过程。
14 0
|
1月前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
31 0
|
1月前
|
算法
❤️算法笔记❤️-(每日一刷-26、删除有序数组的重复项)
❤️算法笔记❤️-(每日一刷-26、删除有序数组的重复项)
23 0
|
29天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
下一篇
无影云桌面