【CPP】交换排序:冒泡排序、快速排序

目录

  • 1.冒泡排序
      • 简介
      • 代码
      • 分析
  • 2.快速排序
    • 2.1霍尔版本
      • 简介
      • 代码
      • 分析
    • 2.2挖坑版本
    • 2.3前后指针版本
    • 2.4非递归的快排
      • 思路
      • 代码

什么是交换排序?
基本思想:所谓 交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。
其中,冒泡排序快速排序 均属于 交换排序

1.冒泡排序

简介

略。
在这里插入图片描述

代码

在这里插入图片描述

分析

最好的时间复杂度:O(N)
最差的时间复杂度:O(N^2)

2.快速排序

基本思想:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

下面是不同版本的快速排序:

2.1霍尔版本

简介

概述:快速排序属于交换排序的一种,是Hoare于1962年提出的一种二叉树结构的交换排序方法

在这里插入图片描述

思路:

  • 先选定key值,右边先走。
  • 右边找小,左边找大,左右交换
  • 重复第二步,直到left和right相遇与key进行交换

问:为什么相遇位置一定比key值小???
答:因为右边先走决定的。
分析:相遇有两种情况:

  • right 遇 left
    这时候相遇点是 left选定的位置
    • 假如说left是已经走过的,left是找大的,但是找到大之后会与right交换,所以left此时是小值。 汇合点是小值。
    • 假如说left一次都没有走过,right一路“滑铁卢”走到left的起始位置,left的起始位置是key值本身,汇合点是key值,key自己与自己交换没有影响。
  • left 遇 right
    能让left找到right,可以说明right已经找到了小,并且此时值并没有发生交换(因为右边先走!),然后此时right是小值,left遇到了right,汇合点也一定是小值。

代码

在这里插入图片描述

分析

这个版本的快排细节比较多,主要有下面坑:

  • left = begin + 1,问题就是当原数组恰好就是有序的时候反而用了快排会被打乱顺序。
  • while(left < right) 相遇即停止,写成小于等于那很容易造成越界问题。
  • while(left < right && arr[right] >= arr[keyi])
    • 容易造成左右指针错过问题
    • 容易导致arr[left] = arr[right] = arr[keyi]死循环问题
  • keyi = left;要及时更新keyi值,因为对于不同的递归下keyi值都是不同的。


快排与希尔排序:

  • 快排与希尔排序是一个量级的,在数据量巨大的情况下,
    • 若重复数据比较多,快排比较快一点;
    • 若重复数据比较少,希尔排序更快一点。
  • 然而序列有序情况下,快排很吃亏,很慢。

序列有序情况下,快排效率低下的原因分析及解决方法:
在这里插入图片描述
有序序列快排时间复杂度:O(N^2)
理想序列快排时间复杂度:O(N*logN)
总结来看,就是因为在有序序列情况下,快排每次的keyi值都是第一个数导致效率编程>了N^2的情况。注:如果是有序序列,几千的数就会因为递归深度太深而挂掉,因为要递归几千次。

结论:所以我们把keyi值选择不固定即可,可以随机选keyi值也可以三数取中(begin,end,mid)取中间值的下标。

解决方案:①三数取中 或 ②随机数选key
在这里插入图片描述

优化:小区间优化
在上面所说的排序中,其中最后三排的数字占了整个序列的大概百分之八十左右,也就是说为了最后三排的数字排序 多调用栈帧百分之八十左右
小区间优化:用插入排序进行优化(插入排序的小区间适应性更好)。
在这里插入图片描述

实际上,在DeBug环境下,效率大概可以略提升一些,感觉有十分之一吧。
在Release环境下,因为编译器对函数栈帧优化作用极大,以至于小区间优化的作用约等于没有,甚至不如没有小区间优化的版本。
正确代码:
在这里插入图片描述

void quickSort(int* arr, int begin, int end) /** begin指区间起始下标,end指区间最后数字下标 */ // 希望[begin,end]有序
{if (begin >= end) return; //begin > end 没有实际意义 ; begin == end 仅有一个数,当作keyi就结束了if (end - begin + 1 < 10) insertSort(arr + begin, end - begin + 1); // 小区间优化else{// 1.先控制单趟快排,希望[begin,key-1] < [key+1,end]int right = end;int left = begin;int midi = getMidi(arr, begin, end);swap(&arr[midi], &arr[begin]);int keyi = begin;while (left < right) // 相遇停止{while (left < right && arr[right] >= arr[keyi]) right--;while (left < right && arr[left] <= arr[keyi]) left++;swap(&arr[right], &arr[left]);}// 交换swap(&arr[keyi], &arr[left]);keyi = left;//更新下一个递归的keti值// 2.再控制整体多个递归quickSort(arr, begin, keyi - 1);quickSort(arr, keyi + 1, end);}
}

思考:为什么这个代码会有问题?
在这里插入图片描述
在这里插入图片描述

2.2挖坑版本

在这里插入图片描述
思路:

  • key先形成坑位
  • 右边先走,找到比key小的,放到左边的坑位
  • 左边再走,找道比key大的,放到右边的坑位
  • 直到left和right相遇

\

// 挖坑法
int PartSort2(int* a, int begin, int end)
{int midi = getMidi(a, begin, end);swap(&a[midi], &a[begin]);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;
}

2.3前后指针版本

在这里插入图片描述
思路:cur是一个评判数字要掠过还是交换的角色,prev是一个保证其走过的路都是小值得一个角色。

  • 选定key值,cur先走
  • cur找到小值,prev++,cur与prev的值交换;cur++
  • cur找到大值,cur++;
int PartSort3(int* a, int begin, int end)
{int midi = getMidi(a, begin, end);swap(&a[midi], &a[begin]);int key = begin;int cur = begin + 1;int prev = begin;while (cur <= end){/*if (a[cur] < a[key]) {prev++; swap(&a[prev], &a[cur]);}*/if (a[cur] < a[key] && ++prev != cur) swap(&a[prev], &a[cur]);cur++;}swap(&a[prev], &a[key]);return prev;
}

2.4非递归的快排

思路

用循环写快排,只需要模拟递归的过程即可。
在这里插入图片描述

代码

在这里插入图片描述


EOF

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

零基础STM32单片机编程入门(一)初识STM32单片机

文章目录 一.概要二.单片机型号命名规则三.STM32F103系统架构四.STM32F103C8T6单片机启动流程五.STM32F103C8T6单片机主要外设资源六.编程过程中芯片数据手册的作用1.单片机外设资源情况2.STM32单片机内部框图3.STM32单片机管脚图4.STM32单片机每个管脚可配功能5.单片机功耗数据…

竞赛选题 python opencv 深度学习 指纹识别算法实现

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; python opencv 深度学习 指纹识别算法实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;4分创新点&#xff1a;4分 该项目较为新颖…

【STM32】STM32通过I2C实现温湿度采集与显示

目录 一、I2C总线通信协议 1.I2C通信特征 2.I2C总线协议 3.软件I2C和硬件I2C 二、stm32通过I2C实现温湿度&#xff08;AHT20&#xff09;采集 1.stm32cube配置 RCC配置&#xff1a; SYS配置&#xff1a; I2C1配置&#xff1a; USART1配置&#xff1a; GPIO配置&#…

day50 1143.最长公共子序列 1035.不相交的线 53. 最大子序和 392.判断子序列

1143. 最长公共子序列 提示 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删…

Excel 解析十六进制并查找

A1 格由多个人名及其考勤情况组成&#xff0c;比如&#xff0c;c 是十六进制的 1100&#xff0c;表示第 1、2 天到场&#xff0c;第 3、4 天缺席。目前只有 4 天的考勤。 AB1alice,c,bob,7,clara,a,mike,9/input: name and presence22/input: the day to be queried 要求根据…

【Linux】基础 I / O

目录 一、C文件操作函数&#xff1a; 二、输入 / 输出 / 错误流&#xff1a; 三、系统文件 I/O open函数&#xff1a; write&#xff1a; read&#xff1a; close&#xff1a; 具体应用&#xff1a; 四、文件描述符(fd): 1、概念&#xff1a; 2、文件管理&#xff1…

计算机网络 —— 网络字节序

网络字节序 1、网络字节序 (Network Byte Order)和本机转换 1、大端、小端字节序 “大端” 和” 小端” 表示多字节值的哪一端存储在该值的起始地址处&#xff1b;小端存储在起始地址处&#xff0c;即是小端字节序&#xff1b;大端存储在起始地址处&#xff0c;即是大端字节…

Pytorch深度解析:Transformer嵌入层源码逐行解读

前言 本部分博客需要先阅读博客&#xff1a; 《Transformer实现以及Pytorch源码解读&#xff08;一&#xff09;-数据输入篇》 作为知识储备。 Embedding使用方式 如下面的代码中所示&#xff0c;embedding一般是先实例化nn.Embedding(vocab_size, embedding_dim)。实例化的…

【shell脚本速成】mysql备份脚本

文章目录 案例需求脚本应用场景&#xff1a;解决问题脚本思路实现代码 &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f388;欢迎踏入我的博客世界&#xff0c;能与您在此邂逅&#xff0c;真是缘分使然&#xff01;&#x1f60a; &#x1f338;愿您在此停留的每一刻…

更改ip后还被封是ip质量的原因吗?

不同的代理IP的质量相同&#xff0c;一般来说可以根据以下几个因素来进行判断&#xff1a; 1.可用率 可用率就是提取的这些代理IP中可以正常使用的比率。假如我们无法使用某个代理IP请求目标网站或者请求超时&#xff0c;那么就代表这个代理不可用&#xff0c;一般来说免费代…

最强铁基超导磁体诞生!科学家基于机器学习设计新研究体系,磁场强度超过先前记录2.7倍

超导现象&#xff0c;自 1911 年被发现以来&#xff0c;始终保持着前沿性与高价值&#xff0c;吸引了大批学者投身其研究中。超导现象是指某些材料在低于特定温度时电阻突然降为零&#xff0c;这不仅是材料学的革命性突破&#xff0c;也为电力传输、磁悬浮交通和医疗成像等领域…

【CentOS7】Linux安装Docker教程(保姆篇)

文章目录 查看是否已安装卸载&#xff08;已安装过&#xff09;docker安装友情提示 更多相关内容可查看 注&#xff1a;本篇为Centos7安装Docker&#xff0c;若为其他系统请理性参考 查看是否已安装 如果已安装&#xff0c;请卸载重新安装 docker --version这里显示已安装 …

mac鼠标自动点击工具:RapidClick for Mac 激活版

RapidClick是一种简单易用的点击工具&#xff0c;它可以帮助用户快速进行连续的鼠标点击操作。该软件可用于自动点击鼠标&#xff0c;从而提高用户在电脑上的效率和速度。RapidClick还具有一些自定义设置&#xff0c;比如点击间隔和点击频率&#xff0c;可以根据用户的需求进行…

Redis-数据结构-跳表详解

Redis概述 Redis-数据结构-跳表详解 跳表&#xff08;Skip List&#xff09;是一种基于并联的链表结构&#xff0c;用于在有序元素序列中快速查找元素的数据结构。 Redis 中广泛使用跳表来实现有序集合&#xff08;Sorted Set&#xff09;这一数据结构。 1.跳表的基本概念和…

Java程序之可爱的小兔兔

题目&#xff1a; 古典问题&#xff0c;有一对兔子&#xff0c;从出生后第3个月起每个月都生一对兔子&#xff0c;小兔子长到第三个月后每个月又生一对兔子&#xff0c;假如兔子都不死&#xff0c;问每个月的兔子总数为多少? 程序分析&#xff1a; 兔子的规律为数列1,1,2,3,…

.locked勒索病毒详解 | 防御措施 | 恢复数据

引言 在数字化飞速发展的今天&#xff0c;我们享受着信息技术带来的便捷与高效&#xff0c;然而&#xff0c;网络安全问题也随之而来&#xff0c;且日益严重。其中&#xff0c;勒索病毒以其狡猾的传播方式和巨大的破坏性&#xff0c;成为了网络安全领域中的一大难题。.locked勒…

捷瑞数字业绩波动性明显:关联交易不低,募资必要性遭质疑

《港湾商业观察》施子夫 5月22日&#xff0c;山东捷瑞数字科技股份有限公司&#xff08;以下简称&#xff0c;捷瑞数字&#xff09;及保荐机构国新证券披露第三轮问询的回复&#xff0c;继续推进北交所上市进程。 从2023年6月递表开始&#xff0c;监管层已下发三轮审核问询函…

项目训练营第二天

项目训练营第二天 用户登录逻辑 1、账户名不少于4位 2、密码不少于8位 3、数据库表中能够查询到账户、密码 4、密码查询时用同样加密脱敏处理手段处理后再和数据库中取出字段进行对比&#xff0c;如果账户名未查询到&#xff0c;直接返回null 5、后端设置相应的脱敏后用户的s…

我的常见问题记录

1,maven在idea工具可以正常使用,在命令窗口执行出现问题 代码: E:\test-hello\simple-test>mvn clean compile [INFO] Scanning for projects... [WARNING] [WARNING] Some problems were encountered while building the effective model for org.consola:simple-test:jar…

一个完整的Flutter应用

本文基于以下链接进行细节补充15.2 Flutter APP代码结构 | 《Flutter实战第二版》 代码结构 我们先来创建一个全新的Flutter工程&#xff0c;命名为"github_client_app" 我们在项目根目录下分别创建imgs和fonts、jsons、l10n文件夹 工程目录如下&#xff1a; 在l…