【数据结构】排序之交换排序(冒泡 | 快排)
交换目录
- 1. 前言
- 2. 交换排序
- 3. 冒泡排序
- 3.1 分析
- 3.2 代码实现
- 4. 快速排序
- 4.1 hoare版本
- 4.1.1 分析
- 4.1.2 hoare版本代码
- 4.2 挖坑法
- 4.2.1 分析
- 4.2.2 挖坑法代码实现
- 4.3 前后指针版本
- 4.3.1 分析
- 4.3.2 前后指针版本代码实现
1. 前言
在之前的博客中介绍了插入排序,有需要的可以点这个链接: link,这次来介绍交换排序,包括冒泡和快排。
话不多说,正文开始。
2. 交换排序
基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置。
交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。
交换排序这里介绍冒泡排序和快速排序,来一起看看。
3. 冒泡排序

动图形象的展示了冒泡排序的过程。
冒泡排序的特性总结:
- 冒泡排序是一种非常容易理解的排序
- 时间复杂度:O(N^2)
- 空间复杂度:O(1)
- 稳定性:稳定
3.1 分析
交换排序肯定离不开交换,就先写一个Swap。
void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
同样的方法,先实现单趟排序,如果前一个大于后一个就交换,把最大的放在了最后。
得注意把控区间的位置,如果if中的代码是a[i+1]>a[i],那么上面循环的区间就是从0到n-1。

第一趟的位置在n-1,那么第j趟就是n-j。
所以对于总的来排,就在外面套一个循环,也就是:

来看看使用结果

如果说没有给定的数据已经排好序了,就不用经行交换了,就加一个标志bool exchange = false,如果交换了就变为true。

3.2 代码实现
void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}void BubbleSort(int* a, int n)
{for (int j = 0; j < n; j++){bool exchange = false;for (int i = 1; i < n - j; i++){if (a[i - 1] > a[i]){Swap(&a[i - 1], &a[i]);exchange = true;}}if (exchange == false)break;}}
4. 快速排序
快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法。
其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
快速排序有三种实现方法,下面来介绍。
4.1 hoare版本
hoare版本是怎么实现的?
来看看动图:

可以看到这里,先选取了一个关键的值key,

然后右边边开始走,可以发现,当右边找到第一个比key小的值,就停下来。然后走左边,左边找到第一个比key大的值,然后左右两边交换;交换完,又继续。

当左右两边相遇就结束,然后将key与这个位置交换。

为什么要相遇位置比key的值小?
因为是从右边先走,相遇就有两种情况:
- R遇到L,R没有找到比key小的值,就一直走,直到遇见L,相遇位置是L,比key小。
- L遇到R,R先走,找到小于key的值就停下,L找大,一直找,没有找到,但是遇见R就停下来,相遇位置就是R找到小的位置,也比key要小。
4.1.1 分析
用keyi来记录交换值的下标。
同样先看单趟排序,在上面已经分析了。
首先右边先走,找小,那么它的代码是

左边找大。

但是走到结尾会发生错误,可能会错位,出现right<left的情况,所以在循环里面多加一个判断。

循环出来后就交换。
要让keyi到它最终的位置,就得用while ( left < right)来走,当走完后,交换key和left。任何继续排下一个数。
这里的keyi将区间分为三部分:[begin,keyi-1],keyi,[keyi+1,end]。
如果左边有序,右边有序,那么整体就有序。

用递归实现,当这个区间只有一个值或者没有值时候,结束。否则就调用左区间和右区间。

实现结果:
4.1.2 hoare版本代码
void QuickSort(int* a, int begin, int end)
{if (begin >= end)return;int left = begin, right = end;int keyi = begin;while ( left < right){// 右边找小while (left < right && a[right] >= a[keyi]){--right;}// 左边找大while (left < right && a[left] <= a[keyi]){++left;}Swap(&a[left], &a[right]);}Swap(&a[left], &a[keyi]);keyi = left;// [begin, keyi-1] keyi [keyi+1, end]QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);}
4.2 挖坑法
看动图展示一下:

把左边位置的值先挖出来,用key先保存起来。形成了第一个坑位。

然后右边先走,找到比key要小的值,然后就把这个值,取出来放到这个坑中。
然后形成了新的坑。

然后左边找大,找到大以后,将它扔到坑中。

直到它们两个相遇就终止了,然后把key填上。

4.2.1 分析
挖坑法没有hoare版的复杂,先找到右边找到小放在坑里,左边找到大的放坑里,在相遇时候把key放进去就行。
为了方便递归,重新写递归部分在,将坑位置的值传进去就行。

举个例子实现一下:

4.2.2 挖坑法代码实现
int PartSort2(int* a, int begin, int end)
{int key = a[begin];int hole = begin;while (begin < end){// 右边找小,填到左边的坑while (begin < end && a[end] >= key){--end;}a[hole] = a[end];hole = end;// 左边找大,填到右边的坑while (begin < end && a[begin] <= key){++begin;}a[hole] = a[begin];hole = begin;}a[hole] = key;return hole;
}void QuickSort(int* a, int begin, int end)
{if (begin >= end)return;int keyi = PartSort2(a, begin, end);QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);
}
4.3 前后指针版本

cur遇到比key大的值,就++cur;
cur遇到比key小的值,就++prev,交换prev和cur位置的值

cur先走

当cur遇到比key小的值,
先加加prev,再与cur交换。

然后cur继续往后走,又遇见比key小的

然后先加加prev,再与cur交换。

cur继续往后找小

cur比end大,就结束,然后将key与prev交换。

4.3.1 分析
先定义一下cur和prev,让int cur = prev + 1,int prev = begin。
当cur比key的值小时就继续走,否则就++prev,然后prev与cur交换。
就直接写一个循环就行,将加加放在条件里面。

当cur出去后,再将key与prev交换。
这里也是先写好单趟,然后调用就行。

举个例子看看:

4.3.2 前后指针版本代码实现
int PartSort3(int* a, int begin, int end)
{int keyi = begin;int prev = begin;int cur = prev + 1;while (cur <= end){if (a[cur] < a[keyi] && ++prev != cur)Swap(&a[prev], &a[cur]);++cur;}Swap(&a[prev], &a[keyi]);keyi = prev;return keyi;
}void QuickSort(int* a, int begin, int end)
{if (begin >= end)return;int keyi = PartSort3(a, begin, end);QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);
有问题请指出,大家一起进步吧!
相关文章:
【数据结构】排序之交换排序(冒泡 | 快排)
交换目录 1. 前言2. 交换排序3. 冒泡排序3.1 分析3.2 代码实现 4. 快速排序4.1 hoare版本4.1.1 分析4.1.2 hoare版本代码 4.2 挖坑法4.2.1 分析4.2.2 挖坑法代码实现 4.3 前后指针版本4.3.1 分析4.3.2 前后指针版本代码实现 1. 前言 在之前的博客中介绍了插入排序,…...
AI电商时代开始:阿里能否反杀拼多多
“AI电商时代刚刚开始,对谁都是机会,也是挑战。” 针对阿里员工对于拼多多财报和电商等的讨论,马云在阿里内网罕见地参与了谈论并发言。 阿里巴巴一向雷厉风行,已打响了AI电商的“第一炮”。 根据《晚点LatePost》报道ÿ…...
STC8H系列单片机入门教程之NVC系列语音播报模块(九)
一、模块简述 ● 模组支持3.3V和5V单片机供电系统 ● 标准2.54MM间距排针与外部连接 ● 支持喇叭0.5W/8欧 ● 适合用于超声波距离、电子秤重量、时钟时间、温度、球赛比分等语音播报 二、引脚说明 序号 名称 说明 1 VCC 电源正(3.3V-5V&#…...
认识计算机网络——计算机网络的组成
计算机网络是由多个计算机和网络设备组成的系统,通过通信协议实现数据传输和信息交换。它是现代社会信息技术的重要支撑,广泛应用于各个领域。本文将介绍计算机网络的主要组成部分,包括硬件设备、软件协议和网络服务。 一、硬件设备 计算机网…...
数据的复制
基本概念 数据的复制指的是通过网络链接的多台机器保留相同的副本 为什么要进行数据的复制 使得用户和数据在地理上比较接近,因为大数据要求我们将计算安排在数据存放的位置和我们基本的内存模型不是很一样 ,比如磁盘调入内存之类的。即使系统的一部分…...
【辐射场】3D Gaussian Splatting
三维高斯…喷喷 \, 3D Gaussian Splatting,下文简称3DGS,是好一段时间以来在三维内容创作和三维重建领域比较有热度的一项技术。 它属于基于图像的三维重建方法,意思就是你对现实物体或者场景拍照片,就能给你训练成一个场景模型&a…...
冒泡排序--------(C每日一题)
冒泡排序: 每次将相邻的两个数比较,将小的调到前头--升序 冒泡排序一个结论: n个数要进行n-1轮比较,第j轮要进行n-j次两两比较 循环体代码: int main() {int i, j,n,a[10],t;//n是几个数比较for(j1;j<n-1;j)//控制轮次for…...
每日一练:LeeCode-347. 前 K 个高频元素(中) - 【优先级队列】
本文是力扣LeeCode-347. 前 K 个高频元素 学习与理解过程,本文仅做学习之用,对本题感兴趣的小伙伴可以出门左拐LeeCode。 给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 示例 1: 输…...
<蓝桥杯软件赛>零基础备赛20周--第11周--贪心
报名明年4月蓝桥杯软件赛的同学们,如果你是大一零基础,目前懵懂中,不知该怎么办,可以看看本博客系列:备赛20周合集 20周的完整安排请点击:20周计划 每周发1个博客,共20周。 在QQ群上答疑&#x…...
PowerShell Instal 一键部署TeamCity
前言 TeamCity 是一个通用的 CI/CD 软件平台,可实现灵活的工作流程、协作和开发实践。允许在您的 DevOps 流程中成功实现持续集成、持续交付和持续部署。 系统支持 Centos7,8,9/Redhat7,8,9及复刻系列系统支持 Windows 10,11,2012,2016,2019,2022高版本建议使用9系列系统…...
将“渴望“乐谱写入AT24C02并读出播放
#include <reg51.h> // 包含51单片机寄存器定义的头文件 #include <intrins.h> //包含_nop_()函数定义的头文件 #define OP_READ 0xa1 // 器件地址以及读取操作,0xa1即为1010 0001B #define OP_WRITE 0xa0 // 器件地址以及写…...
Vue独立组件开发-动态组件
文章目录 一、前言二、实现三、优化四、总结五、最后 一、前言 在开发中,你经常会遇到这么一种情况:根据条件动态地切换某个组件,或动态地选择渲染某个组件。 Vue 提供了另外一个内置的组件 <component> 和 is 特性,可以更…...
前端八股文(HTML篇)
目录 1.什么是DOCTYPE,有何用呢? 2.说说对html语义化的理解 3.src和href的区别? 4.title与h1的区别,b与strong的区别,i与em的区别? 5.什么是严格模式与混杂模式? 6.前端页面有哪三层构成,分…...
RivaGAN 水印项目
git地址 https://github.com/DAI-Lab/RivaGAN Dockerfile (/tools下文件为git下的文件) ############################################### # 使用 NVIDIA CUDA 10.0 开发环境作为基础镜像 FROM kaldiasr/kaldi:gpu-ubuntu18.04-cuda10.0 # 设置非交互式安装模式以避免某些命…...
Games101作业5
1.实现Renderer.cpp 中的 Render():为每个像素生成光线 这里你需要为每个像素生成一条对应的光 线,然后调用函数 castRay() 来得到颜色,最后将颜色存储在帧缓冲区的相 应像素中。 我们要做的就是将屏幕空间下的坐标最后转换到世界空间的坐标…...
Golang解决跨域问题【OPTIONS预处理请求】
Golang解决跨域问题 前置知识:跨域问题产生条件及原因 跨域是是因为浏览器的同源策略限制,是浏览器的一种安全机制,服务端之间是不存在跨域的。 所谓同源指的是两个页面具有相同的协议、主机和端口,三者有任一不相同即会产生跨域…...
复试 || 就业day05(2023.12.31)算法篇
文章目录 前言找不同最长回文串找到所有数组中消失的数字下一个更大元素 I键盘行 前言 💫你好,我是辰chen,本文旨在准备考研复试或就业 💫文章题目大多来自于 leetcode,当然也可能来自洛谷或其他刷题平台 💫…...
Spring-4-代理
前面提到过,在Spring中有两种类型的代理:使用JDK Proxy类创建的JDK代理以及使用CGLIB Enhancer类创建的基于CGLIB的代理。 你可能想知道这两种代理之间有什么区别,以及为什么 Spring需要两种代理类型。 在本节中,将详细研究代理…...
设计模式:抽象工厂模式(讲故事易懂)
抽象工厂模式 定义:将有关联关系的系列产品放到一个工厂里,通过该工厂生产一系列产品。 设计模式有三大分类:创建型模式、结构型模式、行为型模式 抽象工厂模式属于创建型模式 上篇 工厂方法模式 提到工厂方法模式中每个工厂只生产一种特定…...
C语言中的Strict Aliasing Rule
文章目录 前言没有警告不代表没有问题目前的应对方法 前言 很久没写了,水一篇。 最近有个代码在gcc 4.8.5上编译失败。编译失败的提示是: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werrorstrict-aliasing]查了下…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
