数据结构与算法基础-学习-31-交换排序之冒泡排序、快速排序

排序的其他相关知识点和源码分享可以参考之前的博客:   

《数据结构与算法基础-学习-30-插入排序之直接插入排序、二分插入排序、希尔排序》

一、交换排序基本思想

两两比较,如果发生逆序则交换位置,直到所有数据记录都排好序为止。

二、冒泡排序基本思想

每趟不断地将数据记录两两比较,并按照升序或降序规则进行交换。

三、冒泡排序算法实现思路

这里的哨兵起的是临时变量的作用,在交换元素时使用。

我们还是以升序为例。

1、第一趟

一共有7个元素,需要比较6次,因为没有8号位。

(1)1小于2,不要交换,继续

(2)2小于8,不要交换,继续

(3)8大于5,需要交换,继续

(4)8大于4,需要交换,继续

(5)8大于6,需要交换,继续

(6)8大于3,需要交换,6次比较完,已经把最大值8放到了最后一位,那下一趟比较时,就不需要比较8了。

2、第二趟

一共有6个元素需要比较,总共需要比较5次,因为7号位的8已经完成排序。

(1)1小于2,不要交换,继续

(2)2小于5,不要交换,继续

(3)5大于4,需要交换,继续

(4)5小于6,不要需要交换,继续

(5)6大于3,需要交换,5次比较完,已经把最大值6放到了最后一位,那下一趟比较时,就不需要比较6,8了。

3、第三趟

一共有5个元素需要比较,总共需要比较4次,因为6和8已经完成排序。

规律都知道了,我们这就快进一些,跳过了一些对比步骤。

1,2,3,4,5都是升序不需要移动。

(1)5大于3,需要交换,4次比较完,已经把最大值5放到了最后一位,那下一趟比较时,就不需要比较5,6,8了。

4、第四趟

一共有4个元素需要比较,总共需要比较4次,因为5,6和8已经完成排序。

规律都知道了,我们这就快进一些,跳过了一些对比步骤。

1,2,4都是升序不需要移动。

(1)4大于3,需要交换,3次比较完,已经把最大值4放到了最后一位,那下一趟比较时,就不需要比较4,5,6,8了。

5、第五趟

一共有4个元素需要比较,总共需要比较3次,因为4,5,6和8已经完成排序。

1,2,3,4就是升序的,没有交换元素,说明序列已经是有序的,排序完成。

四、冒泡排序算法源码

1、BubbleSortSentrySqQueue

Status BubbleSortSentrySqQueue(SqQueue* Queue)
{
    JudgeAllNullPointer(Queue);

    if (Queue->Flag != INT_TYPE_FLAG)
    {
        return FailFlag;
    }

    int*         Array    = (int*)(Queue->Data);
    int          SwapFlag = 0;
    QueueLenType i;
    QueueLenType j;

    for (i = 1; i < Queue->SqQueueLen - 1; i++)//长度n,比较(n - 1)趟。
    {
        SwapFlag = 0;
        for (j = 1; j < Queue->SqQueueLen - i; j++)//每趟,比较 (n - 第i趟) 次。找个测试数据更明显,好理解
        {
            if (Array[j] > Array[j + 1])
            {
                Array[0]     = Array[j + 1];
                Array[j + 1] = Array[j];
                Array[j]     = Array[0];
                SwapFlag     = 1;
            }
        }
        if (SwapFlag == 0)//如果某一趟不需要进行交换,说明所有元素都是有序的,退出循环。
        {
            break;
        }
    }
    
    LogFormat(Debug,"Bubble Sort SqQueue OK.\n");

    return SuccessFlag;
}

五、冒泡排序算法效率

情况时间复杂度是否稳定
最好O(n)稳定
最坏O(n^2)
平均O(n^2)

最好的情况例如冒泡升序排序,数据是升序排列的,只需要比较n-1次即可,不需要移动元素。

最坏的情况例如冒泡升序排序,数据是降序排列的,

(1)需要比较次数为:

长度为n的序列,需要比较n-1次,每次少比一次,直到1为止,可以使用等差求和公式:

((n - 1) + 1) * (n - 1) / 2 = (n^2 - n)/ 2

(2)需要移动次数为:

每比较一次,需要交换一次,交换需要临时变量存放,一共需要三步,所以乘以3。

                Array[0]     = Array[j + 1];
                Array[j + 1] = Array[j];
                Array[j]     = Array[0];

(n^2 - n)/ 2 * 3。

六、冒泡排序Linux环境编译测试

[gbase@czg2 Sort]$ time ./TestSort 
2023-9-1--[ Debug ]--Init SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,10 ,9 ,8 ,7 ,6 ,5 ,4 ,3 ,2 ,1 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 11
SqQueueMaxLen  : 11
Flag           : INT_TYPE_FLAG
2023-9-1--[ Debug ]--Bubble Sort SqQueue OK.
2023-9-1--[ Info  ]--Sort Function Elapsed Time   : 0 s
2023-9-1--[ Info  ]--SqQueue Data   :
Data           : [ 1 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 11
SqQueueMaxLen  : 11
Flag           : INT_TYPE_FLAG
2023-9-1--[ Debug ]--Destroy SqQueue OK

real    0m0.002s
user    0m0.000s
sys     0m0.002s

七、快速排序基本思想

快速排序是改进的交换排序。

1、任取一个元素为中心(一般是第一个元素)。

2、所有比它小的元素一律前放,比它大的元素一律后放,形成左右两个子表。

3、对各子表重新选择中心元素并依照上述规则调整。

4、直到每个子表的元素只剩下一个。

八、快速排序算法实现思路

这里的哨兵位也是起到存放临时变量的作用的。

1、第一趟

1号位的3作为中间点,存放在哨兵位0中,那Low位置的元素就是空的了。

哨兵位的3和High的1进行比较,3大于1,将High的1填写到Low上,那样High的位置就空出来了。我们开始从Low找。

哨兵位的3和Low的1进行比较,3大于1,在3的左边,不需要移动,Low向右移动。

哨兵位的3和Low的2进行比较,3大于2,在3的左边,不需要移动,Low向右移动。

哨兵位的3和Low的8进行比较,8大于3,在3的右边,需要移动把Low的8移动到High的位置,Low的位置空了,开始High位置和哨兵进行比较,是不是发现了什么,左边有空位了,就去右边找,找,右边空了,就去左边找,很有规律性。

哨兵位的3和High的8进行比较,8大于3,在3的右边,不需要移动,High向左移动。

哨兵位的3和High的6进行比较,6大于3,在3的右边,不需要移动,High向左移动。

哨兵位的3和High的4进行比较,4大于3,在3的右边,不需要移动,High向左移动。

Low和High重合,说明Low左边的都比3小,右边的都比3大,把3填到Low的位置。

Low左边已经排好序了,我们开始排序右边的这些元素。

2、第二趟

还是以第一个Low的位置为中心点,这样Low的位置就空出来了,哨兵和HIgh为的5进行比较,发现比8小,HIgh左移。

哨兵位的5和High的6进行比较,6大于5,在5的右边,不需要移动,High向左移动。

哨兵位的5和High的4进行比较,5大于4,在5的左边,Low填上4,那High的位置就空出来了,我们开始移动Low。

哨兵位的5和Low的4进行比较,5大于4,在3的左边,不需要移动,Low向右移动。

发现Low和High重合,将哨兵填写到Low上,这一段有序了,整个序列就完成了排序。

九、快速排序算法源码

1、QuickSortPartionSentrySqQueue

将Low到High之间元素根据Low为中间值进行分区,返回中间值的最终索引位置。

//返回中间点索引。
QueueLenType QuickSortPartionSentrySqQueue(SqQueue* Queue, QueueLenType Low, QueueLenType High)
{
    JudgeAllNullPointer(Queue);
    
    int* Array = (int*)(Queue->Data);
    Array[0]   = Array[Low];

    while (Low < High)
    {
        while (Low < High && Array[0] <= Array[High])//大于等于中间点的值放右边。
        {
            High--;
        }
        Array[Low] = Array[High];
        while (Low < High && Array[0] > Array[Low])//小于中间点的值放左边。
        {
            Low++;
        }
        Array[High] = Array[Low];
    }
    Array[Low] = Array[0];

    return Low;
}

2、QuickSortRecurtionSentrySqQueue

void QuickSortRecurtionSentrySqQueue(SqQueue* Queue, QueueLenType Low, QueueLenType High)
{
    JudgeAllNullPointer(Queue);

    if (Low >= High)//退出条件,High必须要大于low。
    {
        return;
    }
    QueueLenType PivotIndex = QuickSortPartionSentrySqQueue(Queue, Low, High);

    QuickSortRecurtionSentrySqQueue(Queue, Low, PivotIndex - 1);
    QuickSortRecurtionSentrySqQueue(Queue, PivotIndex + 1, High);
}

十、快速排序算法效率

情况时间复杂度是否稳定
最好O(n * log2^n)不稳定
最坏O(n^2)
平均O(n * log2^n)

1、快速排序不是原地排序,因为递归方法使用了系统栈,不用递归,需要用用户栈实现。

2、快速排序不适用于对原本有序或基本有序的记录序列进行排序。

3、划分元素的选取是影响时间性能的关键。

4、输入数据次序越乱,所选划分值随机性越好,排序速度越快,快速排序不是自然排序方法。

5、升序快速排序算法使用在倒序排序序列上,会触发最坏的情况,使算法退化为冒泡排序。

十一、快速排序Linux环境编译测试

[gbase@czg2 Sort]$ time ./TestSort 
2023-9-1--[ Debug ]--Init SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--Enter SqQueue OK
2023-9-1--[ Debug ]--SqQueue Data   :
Data           : [ 0 ,10 ,9 ,8 ,7 ,6 ,5 ,4 ,3 ,2 ,1 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 11
SqQueueMaxLen  : 11
Flag           : INT_TYPE_FLAG
2023-9-1--[ Debug ]--Quick Sort Sentry SqQueue OK.
2023-9-1--[ Info  ]--Sort Function Elapsed Time   : 0 s
2023-9-1--[ Info  ]--SqQueue Data   :
Data           : [ 4 ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ]
FrontIndex     : 0
RearIndex      : 0
SqQueueLen     : 11
SqQueueMaxLen  : 11
Flag           : INT_TYPE_FLAG
2023-9-1--[ Debug ]--Destroy SqQueue OK

real    0m0.002s
user    0m0.000s
sys     0m0.002s

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/99245.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

无涯教程-Android - Style Demo Example函数

下面的示例演示如何将样式用于单个元素。让我们开始按照以下步骤创建一个简单的Android应用程序- 步骤说明 1 您将使用Android Studio IDE创建一个Android应用程序,并在 com.example.saira_000.myapplication 包下将其命名为 myapplication ,如中所述您好世界Example一章。 2 …

常用Web漏洞扫描工具汇总(持续更新中)

常用Web漏洞扫描工具汇总 常用Web漏洞扫描工具汇总1、AWVS&#xff0c;2、OWASP Zed&#xff08;ZAP&#xff09;&#xff0c;3、Nikto&#xff0c;4、BurpSuite&#xff0c;5、Nessus&#xff0c;6、nmap7、X-ray还有很多不是非常知名&#xff0c;但可能也很大牌、也较常见的。…

el-date-picker限制选择的时间范围

<el-date-pickersize"mini"v-model"dateTime"value-format"yyyy-MM-dd HH:mm:ss"type"datetimerange"range-separator"~"start-placeholder"开始日期"end-placeholder"结束日期":picker-options&quo…

Fooocus启动时modules报错的解决方法

原理&#xff1a;是由于其他程序的安装导致modules的版本不对&#xff0c;先卸载现有版本&#xff0c;再运行run.bat让其自动安装响应的modules版本。 1、cmd运行windows dos终端。 2、将Fooocus_win64_1-1-1035文件夹备份&#xff0c;rename为Fooocus_win64_1-1-1035backup文…

【ES6】Promise的入门介绍

Promise 是 JavaScript 中的一个对象&#xff0c;用于处理异步操作。Promise 对象代表一个最终可能完成&#xff08;并得到结果&#xff09;或失败&#xff08;并被拒绝&#xff09;的操作&#xff0c;以及其结果的值。 一个 Promise 有三种状态&#xff1a; Pending&#xf…

Spring容器及实例化

一、前言 Spring 容器是 Spring 框架的核心部分&#xff0c;它负责管理和组织应用程序中的对象&#xff08;Bean&#xff09;。Spring 容器负责创建、配置和组装这些对象&#xff0c;并且可以在需要时将它们提供给应用程序的其他部分。 Spring 容器提供了两种主要类型的容器&…

blender 火焰粒子

效果展示 创建火焰模型 新建立方体&#xff08;shift A &#xff09;,添加表面细分修改器&#xff08;ctrl 2 &#xff09;&#xff0c;视图层级调整为 3 &#xff0c;这样布线更密集&#xff1b; 右键将模型转换为网格&#xff0c;tab 进入编辑模式&#xff0c;7 切换到顶…

ssm农业视频实时发布管理系统源码

ssm农业视频实时发布管理系统源码108 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm package com.controller;import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; impo…

Java 读取TIFF JPEG GIF PNG PDF

Java 读取TIFF JPEG GIF PNG PDF 本文解决方法基于开源 tesseract 下载适合自己系统版本的tesseract &#xff0c;官网链接&#xff1a;https://digi.bib.uni-mannheim.de/tesseract/ 2. 下载之后安装&#xff0c;安装的时候选择选择语言包&#xff0c;我选择了中文和英文 3.…

以GitFlow分支模型为基准的Git版本分支管理流程

以GitFlow分支模型为基准的Git版本分支管理流程 文章目录 以GitFlow分支模型为基准的Git版本分支管理流程GitFlow分支模型中的主要概念GitFlow的分支管理流程图版本号说明借助插件Git Flow Integration Plus实现分支模型管理其他模型TBD模型阿里AoneFlow模型 GitFlow分支模型中…

【C++入门】string类常用方法(万字详解)

目录 1.STL简介1.1什么是STL1.2STL的版本1.3STL的六大组件1.4STL的缺陷 2.string类的使用2.1C语言中的字符串2.2标准库中的string类2.3string类的常用接口说明 &#xff08;只讲解最常用的接口&#xff09;2.3.1string类对象的常见构造2.3.2 string类对象的容量操作2.3.3string…

count(1)、count(*)和count(列名)及官网解释

最近面试并且看网上的资料说count(1)和count(*)参差不同&#xff0c;就查看了官网&#xff0c;特别记录一下。 共同点&#xff1a;都是用来统计我们的表中的行数不同点&#xff1a; 执行效果上来说&#xff1a;count(1)和count(*)都不会忽略列值为null的行数&#xff0c;而cou…

一篇文章带你了解-selenium工作原理详解

前言 Selenium是一个用于Web应用程序自动化测试工具。Selenium测试直接运行在浏览器中&#xff0c;就像真正的用户在操作一样。支持的浏览器包括IE&#xff08;7, 8, 9, 10, 11&#xff09;&#xff0c;Mozilla Firefox&#xff0c;Safari&#xff0c;Google Chrome&#xff0c…

无涯教程-Android - ToggleButton函数

ToggleButton将已选中/未选中状态显示为按钮。它基本上是一个带有指示灯的开/关按钮。 Toggle Button ToggleButton属性 以下是与ToggleButton控件相关的重要属性。您可以查看Android官方文档以获取属性的完整列表以及可以在运行时更改这些属性的相关方法。 Sr.No.Attribute…

linuxdeploy安装CentOS7搭建django服务

目录 一、busybox安装 二、linuxdeploy安装 三、linuxdeploy软件设置及安装 四、CentOS基础环境配置 五、CentOS7 上安装Python3.8.10 六、systemctl的替代品 七、CentOS7 上安装mysql5.2.27数据库 八、CentOS7 上安装Nginx服务 九、Django项目应用部署 参考文献: 一…

删除、移动、复制文件时总是要卡在99%一段时间解决方法

Win10文件夹重命名、移动、删除等操作卡顿3-5秒。 原因分析: 查看发现&#xff0c;卡顿期间资源管理器无响应&#xff0c;并且其高度占用CPU资源&#xff0c;但是对于非文件夹文件操作没有问题。 解决方案: 1、双击“此电脑”&#xff0c;选择“查看”&#xff0c;再选择“选…

STM32启动模式详解

文章目录 前置知识1. 单片机最小系统组成2. BOOT电路3. 三种启动模式4. 存储器映射 从主FLASH启动从系统存储区启动从SRAM启动 前置知识 1. 单片机最小系统组成 一个单片机最小系统由电源、晶振、下载电路、BOOT电路、和复位电路组成。少一个单片机都启动不了。 2. BOOT电路 …

Java设计模式:四、行为型模式-06:观察者模式

文章目录 一、定义&#xff1a;观察者模式二、模拟场景&#xff1a;观察者模式2.1 观察者模式2.2 引入依赖2.3 工程结构2.4 模拟摇号2.4.1 摇号服务接口2.4.2 摇号返回结果类 三、违背方案&#xff1a;观察者模式3.0 引入依赖3.1 工程结构3.2 添加摇号接口和实现3.2.1 摇号服务…

全新纠错码将量子计算提效10倍!

上周&#xff0c;来自两个研究小组的最新模拟报告称&#xff0c;一类新兴的量子纠错码的效率比目前的“黄金标准”&#xff08;即表面码&#xff09;高出一个数量级。 量子纠错码的工作原理都是将大量容易出错的量子比特转换成更小的“受保护”量子比特&#xff0c;这些量子比特…

Linux-安装redis6.2.1及主备复制模式(replication)

Linux-安装redis6.2.1 下载redis6.2.1资源上传至安装目录解压及编译解压修改名称编译 修改配置文件主节点从节点 启动及测试启动主节点从节点 测试 下载redis6.2.1资源 地址》https://redis.io/download/ 上传至安装目录 例&#xff1a;/data/replication/ 解压及编译 解…