【CPP】选择排序:冒泡排序、快速排序

news2024/10/22 11:29:11

目录

  • 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.coloradmin.cn/o/1843958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python基础教程(二十六):对接MongoDB

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

maxKb+ollama+lama2-chinese 基于知识库+本地模型的知识问答系统

maxKbollamalama2-chinese 基于知识库本地模型的知识问答系统 搭建步骤 搭建maxKb docker run -d --namemaxkb -p 8080:8080 -v ~/.maxkb:/var/lib/postgresql/data cr2.fit2cloud.com/1panel/maxkb# 用户名: admin # 密码: MaxKB123..github的访问地址&#xff1a;https://…

压缩字体文件包大小pingfang等通用方法

压缩字体包大小 1、确保已经安装python 借助python环境&#xff0c;安装fonttools插件&#xff1a; 如果运行pip失败&#xff0c;注意看一下自己的环境变量是否错误&#xff1a; 在用户环境变量中与python安装目录下scripts相对应 pip install fonttools2、如果显示下载超…

家用电器信息管理系统

摘 要 随着互联网的快速发展&#xff0c;传统家电行业受到冲击&#xff0c;逐渐向智能家居市场转型。因此&#xff0c;智能家居无疑是一个有着巨大市场需求和新兴发展空间的新兴产业&#xff0c;也是人们追求安全、便捷、舒适的生活方式的必然趋势。互联网推动了我国传统家居产…

TCP编程

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 由于TCP连接具有安全可靠的特性&#xff0c;所以TCP应用更为广泛。创建TCP连接时&#xff0c;主动发起连接的叫客户端&#xff0c;被动响应连接的叫服…

华为设备SSH远程访问配置实验简述

一、实验需求: 1、AR1模拟电脑SSH 访问AR2路由器。 二、实验步骤&#xff1a; 1、AR1和AR2接口配置IP&#xff0c;实现链路通信。 2、AR2配置AAA模式 配置用户及密码 配置用户访问级别 配置用户SSH 访问服务 AR2配置远程服务数量 配置用户远程访问模式为AAA 配置允许登录接入用…

东芝-Soft Limit 报警及其解决办法

灵感来源与生活,在生活中总能有意想不到的惊喜,下面来看看小编今天的惊喜!!! 今天不知道怎么了,有人来找就说是机器人坏了,一直报警,重启关机回原点也没有用。 意外到来,只能使用手柄将控制器打手动,来看看报警显示什么。 下面就看到了这,我靠第一次看见,只能看看手…

【决战欧洲之巅】苏格兰VS瑞士-AI预测走地数据

初步分析 苏格兰队是欧洲杯的老牌球队&#xff0c;虽然首场比赛表现不佳&#xff0c;但他们的实力不容小觑。苏格兰在预选赛中表现出色&#xff0c;以小组第二的身份晋级&#xff0c;并拥有包括多名英超球员在内的强大阵容&#xff0c;如曼联中场麦克托米奈和利物浦右后卫罗伯…

【Android面试八股文】你刚刚提到了V2签名使用美团的Walle实现多渠道打包,那么你能讲一讲Android 签名的 v1、v2、v3、v4版本的区别吗?

文章目录 前言一、简介二、APK 签名方案 v1 (JAR签名)2.1. 签名过程2.2 验证过程2.3 详细例子2.4 优缺点2.5 美团基于V1版本的多渠道打包方案三、APK 签名方案 v23.1 为什么要设计APK 签名方案 v2 ?3.2 APK 签名方案 v2 : 签名前和签名后的 APK3.2.1 签名前和签名后的 APK3.2…

后端不提供文件流接口,前台js使用a标签实现当前表格数据(数组非blob数据)下载成Excel

前言&#xff1a;开发过程中遇到的一些业务场景&#xff0c;如果第三方不让使用&#xff0c;后端不提供接口&#xff0c;就只能拿到table数据(Array)&#xff0c;实现excel文件下载。 废话不多说&#xff0c;直接上代码&#xff0c;方法后续自行封装即可&#xff1a; functio…

7亿中国男人,今年夏天都在穿什么?

文丨郭梦仪 北京气温已经逼近38度&#xff0c;注重防晒的人群中这次多了男人的身影。 程序员宇宙中心&#xff0c;清河万象汇西区&#xff0c;小米su7吸引众多男士前来观摩&#xff0c;和对面蕉下门店里的“防晒衣大军”恰好呼应上了。 北京清河万象汇的防晒衣专卖店 夏日将…

C++ 计算凸包点的最小旋转矩形

RotateRect.h #include <vector>/** * brief 计算点集最小旋转外接矩形 */ class RotateRect { public:enum { CALIPERS_MAXHEIGHT 0, CALIPERS_MINAREARECT 1, CALIPERS_MAXDIST 2 };struct Point {float x, y;};using Points std::vector<Point>;struct Size…

ASP .Net Core创建一个httppost请求并添加证书

ASP .Net Core创建一个httppost请求并添加证书 创建.net Core程序&#xff0c;使用自签名证书&#xff0c;可以处理https的get和post请求。 创建证书 创建自签名证书的流程可以在这里查看&#xff1a; https://blog.csdn.net/GoodCooking/article/details/139815278创建完毕…

【Python】一文向您详细解析内置装饰器 @lru_cache

【Python】一文向您详细解析内置装饰器 lru_cache 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通本硕&a…

鸿蒙开发通信与连接:【@ohos.nfc.tag (标准NFC-Tag)】

标准NFC-Tag 本模块主要用于操作及管理NFC Tag。 说明&#xff1a; 本模块首批接口从API version 8开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import tag from ohos.nfc.tag;tag.getNfcATag getNfcATag(tagInfo: TagInfo): Nf…

劲爆!Kimi月之暗面可以接入微信,创建自己个性化的AI Agent(人工智能体) (一)

前言 随着人工智能技术的不断发展&#xff0c;越来越多的企业和个人开始关注如何利用AI技术提升用户体验和交互效果。本文将介绍如何使用抖音的扣子&#xff08;Douyin Button&#xff09;配置自己的AI Agent&#xff0c;搭载kimi, 实现智能互动&#xff0c;提升用户体验。 k…

【Python机器学习实战】 | 基于PCA主成分分析技术读入空气质量监测数据进行数据预处理并计算空气质量综合评测结果

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

LeetCode 1164, 125, 94

目录 1164. 指定日期的产品价格题目链接表要求知识点思路代码 125. 验证回文串题目链接标签简单版思路代码 复杂版思路代码 94. 二叉树的中序遍历题目链接标签递归思路代码 迭代思路代码 1164. 指定日期的产品价格 题目链接 1164. 指定日期的产品价格 表 表Products的字段为…

LVGL使用GUI Guider配置STM32界面详细笔记教程

0、说明 接着前面几篇博客对LVGL的使用和介绍&#xff0c;这篇博客主要是使用和介绍快速配置LVGL图形界面编程的工具&#xff0c;GUI Guider。本文使用的工程代码&#xff0c;均是基于前几篇博客的基础上的&#xff0c;如需下载已配置好的LVGL-MCU工程环境&#xff0c;可通过如…

docker启动nacos挂载目录并修改配置文件

1 通过 Docker 拉取 nacos 镜像 docker pull nacos/nacos-server:v2.1.22 创建宿主机挂载目录 # 用于挂载 nacos 的日志 mkdir -p /mydata/nacos_home/logs/ # 用于挂载 nacos 的配置 mkdir -p /mydata/nacos_home/conf/ # 用于挂载 nacos 的数据 mkdir -p /mydata/nacos_hom…