【数据结构】8.3 交换排序

news2024/11/16 5:50:50

文章目录

  • 1. 冒泡排序
    • 冒泡排序算法
    • 冒泡排序算法分析
  • 2. 快速排序
    • 快速排序算法
    • 快速排序算法分析

基本思想

  • 每两个元素之间互相比较,如果发现大小关系相反,则将他们交换过来,直到所有记录都排好序为止。
  • 假设希望是从小到大来排序,结果两个数的位置为 10、9, 这时候就需要交换了。

常见的交换排序方法

  1. 冒泡排序:O(n2)。
  2. 快速排序:O(nlog₂n)。

1. 冒泡排序

基本思想

每一趟将两两相邻的元素进行比较,小的放左边,大的放右边(交换数据),按照递增来排序,不满足条件就交换数据,满足则不管。

  • 将某个数排到最终的位置,这一轮叫一趟冒泡排序

在这里插入图片描述

  • 每一趟冒泡排序可以让 1 个元素走到最终位置.
    • 对于 6 个元素要进行 5 趟冒泡排序。
    • n 个元素要进行 n-1 趟冒泡排序

在这里插入图片描述

冒泡排序过程(升序)

初始:21,25,49,25*,16,08 ;n = 6。

  1. 第 2 趟
    • 第 1 趟结束后:21,25,25*,16,08,49
    • 第 1 趟结束之后,49 已经有序了,那么下一趟就不用管它了。

在这里插入图片描述

  1. 第 2 趟
    • 第 2 趟结束后:21,25,16,08,25*,49
    • 继续下一趟,每一趟增加一个有序元素。

在这里插入图片描述

  1. 第 3 趟结果:21,16,08,25,25*,49
  2. 第 4 趟结果:16,08,21,25,25*,49
  3. 第 5 趟结果:08,16,21,25,25*,49

总结

  • n 个元素,总共需要 n-1 趟冒泡排序
  • 第 m 趟需要比较 n-m 次
    • 第 1 趟需要比较 5 次,第 2 趟 4 次,第 3 趟 3 次…… 。每一趟的排序的趟数 + 这趟的比较次数 = 元素个数 n 。

冒泡排序算法

//对顺序表L左冒泡排序
void bubble_sort(SqList &L)
{
		int m,i,j;
		RedType x;//交换临时存储

		for(m = 1;m <= n-1;m++)//总共需要m(n-1)趟冒泡排序
		{
				for(j = 1;j <= n-m;j++)//每一趟需要比较n-m次
				{
						if(L.r[j].key > L.r[j+1].key)//前面的比后面的大,发生逆序
						{
								x = L.r[j];
								L.r[j] = L.r[j+1];
								L.r[j+1] = x;
								//交换元素位置
						}
				}
		}
}

冒泡排序优点

  • 优点:每趟结束时,不仅能挤出一个最大值到最后面位置,还能同时部分理顺其他元素;

如何提高效率?

  • 一旦某一趟比较时不出现记录交换,则说明已经排好序了,就可以结束本算法来提高效率。

冒泡排序算法改进

在这里插入图片描述

当第 5 趟结束的时候,之前和之后的元素都已经有序了,所以后面的第 6、7 趟纯属于原地打转,浪费时间。

  • 未发生交换时,后面几趟可以省略。
//对顺序表L进行改进的冒泡排序
void bubble_sort(SqList &L)
{
		int m,i,j;
		flag = 1;//flag作为是否有交换的标记
		RedType x;
	
		for(m = 1;m <= n-1 && flag == 1;m++)
		{
				flag = 0;
				for(j = 1;j <= m;j++)
				{
						if(L.r[j].key > L.r[j+1].key)//发生逆序
						{
								flag = 1;//发生交换,让flag为1,
								//若本趟没有发生交换,则flag保持为0,让最外层的for循环进不来
								
								x = L.r[j];
								L.r[j] = L.r[j+1];
								L.r[j+1] = x;
								//交换元素
						}
				}
		}
}

冒泡排序算法分析

时间复杂度

最好情况(正序)

  • 比较次数:n-1 次。
  • 移动次数:0次。

最坏情况(逆序)

  • 比较次数:

在这里插入图片描述

  • 移动次数:

在这里插入图片描述

冒泡排序的算法评价

  • 冒泡排序最好时间复杂度是 O(n)
  • 冒泡排序最欢时间复杂度为 O(n2)
  • 冒泡排序平均时间复杂度为 O(n2)
  • 冒泡排序算法中增加一个辅助空间 temp,辅助空间为 S(n) = O(1)
  • 冒泡排序时稳定的(相同元素排好序后相对位置不变)。

2. 快速排序

由冒跑排序改进的交换排序

基本思想

  • 从需要排序的数据当中,任取一个元素(通常取第一个)为中心
  • 将所有比它的元素一律往前放,比它的元素一律往后放,形成左右两个子表
  • 接下来将左右两个子表用同样的方法进行排序(感觉和二叉排序树蛮像的),
  • 直到每个子表的元素只剩一个

举个例子

  1. 首先先选择第一个元素为中心点,然后划分左右子表。

在这里插入图片描述
在这里插入图片描述

  1. 子表也是用同样的方法排序,选择第一个为中心然后划分左右区。

在这里插入图片描述

  1. 当子表中只剩一个元素的时候,就不需要再划分了,说明已经排好位置了。

在这里插入图片描述
在这里插入图片描述

分析

  • 基本思想:通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录进行排序,以达到整个序列有序。
  • 具体实现:选定一个中间数作为参考,所有元素与之比较,小的调到其左边,大的调到其右边。
  • (枢轴)中间数:可以是第一个数、最后一个数、最中间一个数、任选一个数等。

算法步骤

一趟快速排序的具体步骤如下:

  1. 选择待排序表中的第一个记录作为枢轴,将枢轴记录暂时存到 r[0] 的位置上。
    • 另外设置两个指针 low 和 high ,初始时分别指向表的下界和上届(第一趟时,low = 1; high = L.length;)。
  2. 从表的最右测位置依次向左搜索,找到第一个关键字小于枢轴关键字 pivotkey 的记录,将其移动到 low 处。
    • 具体操作:当 low < high 时,将 high 所指记录的关键字大于等于 pivotkey,则向左移动指针 high(执行操作 --high);否则将 high 所指记录与枢轴记录交换。
  3. 然后再从表的最左侧位置,依次向右搜索找到第一个关键字大于 pivotkey 的记录和枢轴记录交换。
    • 具体操作:当 low < high 时,若 low 所指记录的关键字小于等于 pivotkey,则向右移动指针 low(执行操作 ++low);否则将 low 所指记录与枢轴记录交换。
  4. 重复步骤 2、3,直到 low 与 high 相等为止。
    • 此时 low 和 high 的位置即为枢轴在此趟排序中的最终位置,原表被分为两个子表。

在这里插入图片描述

快速排序特点

  1. 每一趟的子表的形成是采用从两头向中间交替式逼近法;
    • 一开始将枢轴元素放在 0 号位置,那么它的位置就空出来了,从后面挑比它小的元素填进来,此时小元素的原来位置就空了,再从前面般比这个移动过去的小的元素大的元素填过去,前挑大后填,后挑小前填,依次类推。
    • 直到 low 和 high 重合了,这个地方就是俺们放中心点的位置。
  2. 由于每趟中对各子表的操作都相似,可采用递归算法

快速排序算法

//对顺序表L左快速排序
void Quick(SqList &L)
{
		Qsort(L,1,L.length);
}

//调用前置初值:low=1;high=L.length
//对顺序L中的子序列L.r[low...high]左快速排序
void Qsort(SqList %L,int low,int high)
{		
		if(low < high) //长度大于1
		{
				pivotloc = partition(L,low,high);
				//将L.r[low...high]一分为二,pivotloc为枢轴元素排好序的位置

				QSort(L,low,pivotloc-1);//对左子表递归排序
				Qsort(L,pivotloc+1,high);//对右子表递归排序
		}
}

//对顺序表L中的子表r[low...high]进行一趟排序,返回中心点位置
int Partition(SqList &L,int low,int high)
{
		L.r[0] = L,r[low];	//用子表中的第一个记录左枢轴记录
		pivotkey = L.r[low].key;	//枢轴记录关键字保存在pivotkey中

		while(low < high)	//从表的两段交替的向中间扫描
		{
				while(low<high && L.r[high].key >= pivotkey)
				{
						--high;
				}
				L.r[low] = L.r[high];	//将比中心点小的元素移到到低端
				
				while(low<high && L.r[low].key <= pivotkey)
				{
						++low;
				}
				L.r[high] = L.r[low];	//将比中心点大的元素移动到高端
		}		

		L.r[low] = L.r[0];	//找到了中心点该存放的位置了,将它存进去
		return low;		//返回中心点存储的位置
}

快速排序算法分析

时间复杂度

  • 可以证明,整个算法的平均时间复杂度: O(nlog₂n)
    • 快速排序的递归算法 Qsort():Q(log₂n)
    • 查找中心点位置算法 Partition():O(n)
  • 就平均计算时间而言,快速排序时我们所讨论的所有内排序方法中最好的一个。

空间复杂度

  • 快速排序不是原地排序
  • 由于程序中使用了递归,需要递归调用栈的支持,而栈的长度取决于递归调用的深度。(即使不使用递归,也需要用用户栈
    • 在平均情况下:需要 O(logn) 的栈空间。
    • 最坏情况下:栈空间可达到 O(n)

稳定性

  • 快速排序是一种不稳定的排序。

在这里插入图片描述

自然性

在这里插入图片描述

  • 由于每次枢轴记录的关键字都是大于其他所有记录的关键字,致使一次划分之后得到的子序列(1)的长度为 0,这时已经退化成为没有改进措施时的冒泡排序。
  • 快速排序不适合对原本就有序或基本有序的记录序列进行排序

总结

  • 划分元素的选取是影响时间性能的关键。
  • 输入数据次序越乱,所选划分元素值的随机性越好,排序速度越快,快速排序不是自然排序方法。
  • 改变划分元素的选取方法,至多只能改变算法平均情况下的世界性能,无法改变最坏情况下的时间性能。
    • 最坏情况下,快速排序的时间复杂度总是 O(n2)

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

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

相关文章

Nginx-反向代理配置学习总结

Nginx-反向代理配置学习总结 正向代理&#xff1a;指的是通过代理服务器 代理浏览器/客户端去重定向请求访问到目标服务器 的一种代理服务&#xff0c;正向代理服务的特点是代理服务器 代理的对象是浏览器/客户端&#xff0c;也就是对于目标服务器 来说浏览器/客户端是隐藏的。…

文件的IO

一、文件的定义狭隘的文件:指你的硬盘上的文件和目录.广义的文件:泛指计算机中的硬件资源,操作系统中,把很多硬件设备和软件资源都抽象成了文件,按照文件的形式统一管理.比如网卡,操作系统也是把网卡抽象成了文件资源,所以说操作网卡其实和操作文件的方式是基本一样的.而我们本…

初识流计算框架Spark

Spark简介 Spark最初由美国加州伯克利大学&#xff08;UCBerkeley&#xff09;的AMP&#xff08;Algorithms, Machines and People&#xff09;实验室于2009年开发&#xff0c;是基于内存计算的大数据并行计算框架&#xff0c;可用于构建大型的、低延迟的数据分析应用程序。Sp…

一刷代码随想录——链表

1.理论基础链表节点的定义&#xff1a;struct ListNode {int val;ListNode* next;ListNode() : val(0), next(nullptr) {}ListNode(int x) : val(x), next(nullptr) {}ListNode(int x, ListNode* next) : val(x), next(next) {} };根据卡哥提示&#xff0c;由于力扣中已经给出如…

C++中拷贝构造函数、拷贝赋值运算符、析构函数、移动构造函数、移动赋值运算符(三/五法则)

1、介绍 三五法则是针对C中类的成员和类对象的操作函数。 三法则是指&#xff1a;拷贝构造函数、拷贝赋值运算符、析构函数。 五法则是在三法则的基础上增加了&#xff1a;移动构造函数、移动赋值运算符。 2、拷贝构造函数 定义&#xff1a;如果构造函数的第一个参数是自身…

Postman前置脚本

位置&#xff1a;作用&#xff1a;调用脚本之前需要执行的代码片段一、产生随机数字生成0-1之间的随机数&#xff0c;包括0&#xff0c;不包括1&#xff1b;var random Math.random();console.log("随机数",random);获取最小值到最大值之前的整数随机数function Get…

2019-ICML-Graph U-Nets

2019-ICML-Graph U-Nets Paper: https://arxiv.org/abs/1905.05178 Code: https://github.com/HongyangGao/Graph-U-Nets 图U-Nets 作者将CNN上的U-Net运用到了图分类上&#xff0c;因为我们主题是图分类&#xff0c;就不对U-Net进行论述了&#xff0c;只对其中的gPool&#…

eureka 读写锁的一点思考

读写锁 读写锁一般实现 读读不互斥 读写互斥 写写互斥 读写锁的好处是&#xff0c;面对读多写多的场景会拥有比较好的表现 一般我们会在读操作加上读锁&#xff0c;写操作加上写锁。但是最近我发现eureka 在使用读写锁的时候是相反的&#xff0c; 也就是说在读操作加上了读锁&…

2023最值得入手的运动耳机是哪款、口碑最好的运动蓝牙耳机推荐

不知道有没有和我一样的小伙伴&#xff0c;在运动时特别喜欢听音乐&#xff0c;每次听到一首合适的音乐&#xff0c;感觉运动起来都更有激情和活力了。所以这时候就需要挑选一款舒适的耳机了。别看市面上各种各样的运动耳机很多&#xff0c;但实际上能真正适合运动的少之又少&a…

oss服务端签名后直传分析与代码实现

文章目录1.简介1.1 普通上传方式1.2 服务端签名后直传3.服务端签名后直传文档3.1 用户向应用服务器请求上传Policy和回调。3.2 应用服务器返回上传Policy和签名给用户。3.3 用户使用Post方法向OSS发送文件上传请求。4.实战开发-后端4.1 pom.xml核心配置4.2 application.yml核心…

Java两大工具库:Commons和Guava(2)

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客。值此新春佳节&#xff0c;我给您拜年啦&#xff5e;祝您在新的一年中所求皆所愿&#xff0c;所行皆坦途&#xff0c;展宏“兔”&#xff0c;有钱“兔”&#xff0c;多喜乐&#xff0c;常安宁&#xff01;开发中有一类应…

如何在es中查询null值

文章目录1、背景2、需求3、准备数据3.1 创建mapping3.2 插入数据4、查询 name字段为null的数据5、查询address不存在或值直接为null的数据6、参考链接1、背景 在我们向es中写入数据时&#xff0c;有些时候数据写入到es中的是null&#xff0c;或者没有写入这个字段&#xff0c;…

离散数学与组合数学-08谓词逻辑

文章目录离散数学与组合数学-08谓词逻辑8.1 谓词的引入8.1.1 引入谓词逻辑8.1.2 个体词与谓词8.2 量词的引入8.2.1 量词引入8.2.2 个体域符号化8.2.3 量词真值确定8.3 谓词符号化举例8.3.1 示例一8.3.2 示例二8.3.3 示例三8.3.4 示例四8.4 谓词合式公式8.4.1 四类符号8.4.2 项8…

MySQL运维(一)MySQL中的日志、Mysql主从复制

MySQL运维(一)MySQL中的日志、Mysql主从复制 1、MySQL日志 1.1 错误日志 错误日志是 MySQL 中最重要的日志之一&#xff0c;它记录了当 mysqld 启动和停止时&#xff0c;以及服务器在运行过程中发生任何严重错误时的相关信息。当数据库出现任何故障导致无法正常使用时&#…

Elasticsearch 需要了解的都在这

ES选主过程&#xff1f;其实ES的选主过程其实没有很高深的算法加持&#xff0c;启动过程中对接点的ID进行排序&#xff0c;取ID最大节点作为Master节点&#xff0c;那么如果选出来的主节点中存储的元信息不是最新的怎么办&#xff1f;其实他是分了2个步骤做这件事&#xff0c;先…

react 项目 中使用 Dllplugin 打包优化技巧

目录 0.React和DLLPlugin 前言 使用步骤 结果截图 主要说明 0.React和DLLPlugin React 是一个用于构建用户界面的 JavaScript 库。它由 Facebook 开发&#xff0c;现在由 Facebook 和一个由个人开发者和公司组成的社区维护。React 允许开发人员构建可重用的 UI 组件并有…

“回文子串、最长回文子序列”总结,动态规划再显神通(Java实现)

目录 一、回文子串 1.1、dp定义 1.2、递推公式 1.3、初始化 1.4、遍历顺序 1.5、解题代码 二、最长回文子序列 2.1、dp定义 2.2、递推公式 2.3、初始化 2.4、遍历顺序 2.5、解题代码 一、回文子串 题目描述&#xff1a; 题目来源&#xff1a;647. 回文子串 1.1、dp定…

解决使用copy.deepcopy()拷贝Tensor或model时报错只支持用户显式创建的Tensor问题

模型训练过程中常需边训练边做validation或在训练完的模型需要做测试&#xff0c;通常的做法当然是先创建model实例然后掉用load_state_dict()装载训练出来的权重到model里再调用model.eval()把模型转为测试模式&#xff0c;这样写对于训练完专门做测试时当然是比较合适的&…

ssm学生心理健康测评网的规划与设计

摘 要 1 Abstract 1 1 绪论 1 1.1 课题背景 1 1.2 课题研究现状 1 1.3 初步设计方法与实施方案 2 1.4 本文研究内容 2 2 系统开发环境 4 2.1 JSP技术介绍 4 2.2 B/S模式 4 2.3 MySQL环境配置 5 3 系统分析 6 3.1 系统可行性分析 6 3.1.…

【模糊神经网络】基于模糊神经网络的倒立摆轨迹跟踪控制

临近春节没啥事做&#xff0c;突然想起前两年未完成的模糊神经网络&#xff0c;当时是学了一段时间&#xff0c;但是到最后矩阵求偏导那块始终不对&#xff0c;最后也不了了之了&#xff0c;趁最近有空&#xff0c;想重新回顾回顾&#xff0c;看看会不会产生新的想法。经过不断…