「数据结构」八大排序1

news2025/4/19 11:42:10

🎇个人主页:Ice_Sugar_7
🎇所属专栏:初阶数据结构
🎇欢迎点赞收藏加关注哦!

文章目录

  • 🍉插入排序
    • 🍌直接插入排序
      • 🥝复杂度及稳定性
    • 🍌希尔排序
      • 🥝预排序
      • 🥝复杂度及稳定性
  • 🍉选择排序
    • 🍌复杂度及稳定性
  • 🍉堆排序
    • 🍌复杂度及稳定性
  • 🍉写在最后

🍉插入排序

插排就是将一个元素插入一个有序序列中合适的位置,分为直接插入排序希尔排序

🍌直接插入排序

流程如下:
①保存待插入的值:假设某一趟中有序序列最后一个元素下标为end,先保存(end+1)位置的元素,保存到临时变量tmp。

②为a[end+1]找到合适的位置:使用while循环,里面比较a[end]和a[end+1]的大小。
若前者<后者,就退出循环
反之,则将a[end]往后挪一位,覆盖掉a[end+1],end减1,然后让tmp继续往前找,直到找到比它小的元素或者end < 0(end<0说明所有元素都比tmp大,那么就应该把tmp放在a[0]),插到该元素后面。

简而言之就是让tmp向前找比它小的元素,找到就插在它的后面;找不到就是插在第一位

③至此,我们排好了一个数据,现在要排列所有元素,只需在外面套上一层for循环
(假设数组有n个元素,注意循环的终止条件是i < n-1,即i最多只能取到n-2,因为是 i 和 i+1 进行比较)

比如:

int a[] = {2,7,1,9,6,5,8};

图解如下:
在这里插入图片描述
在这里插入图片描述

代码如下:

//n为数组元素个数
void InsertSort(int* a, int n) {
	for (int i = 0; i < n-1; i++) {
		int end = i;  //end为有序序列最后一个元素的下标
		int tmp = a[end + 1];  //tmp保存待插入的数据
		while (end >= 0)
		{
			if (a[end + 1] < a[end]) //待插入的数比end小,那么end就向后移动,给待插入的数据挪出位置
				a[end + 1] = a[end];
			else
				break;
			end--;  //更新end,向前找小 
		}
		//找到小或end == -1
		a[end + 1] = tmp;
	}
}

🥝复杂度及稳定性

时间复杂度:第一趟1次,第二趟2次……由等差数列公式可以推出是O(N^2)
空间复杂度:O(1)
稳定性:稳定


🍌希尔排序

希尔排序是直接插入排序的优化。分两步完成:预排序+直接插入排序
预排序的意义:让大的数更快到后面,小的数更快到前面。使序列趋于有序,降低直接插入排序的成本

🥝预排序

直接插入排序是让相邻的元素进行比较。预排序则是让一个元素和与它相隔几个位置的元素比较
比如:

int a[] = {9,1,2,5,7,4,8,6,3,5};

在这里插入图片描述
9、5、8、5可以分为一组;1、7、6也是一组;2、4、3同理
同一组的元素进行比较,排好序。
预排序后得到:
在这里插入图片描述

这样就完成了一次预排序。希尔排序中有多次预排序,每次排完后会缩小间隔、重新分组,然后继续预排序。假设最开始的间隔为gap,那么就一直缩小,gap越小,预排序一次后序列就越趋于有序。直到gap为1,此时就是直接插入排序,这一次排好后序列就有序了

gap每次预排序一般是缩小到上一次的一半,或是1/3(注意gap除以3之后需要+1,保证gap不为0)
代码如下:

void ShellSort(int* a, int n) {
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;  //+1确保gap至少为1,最后一次循环gap == 1
		//一次预排序
		for (int i = 0; i < n - gap; i++)  //i+gap最多取到n-1
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (a[end] > tmp)
					a[end+gap] = a[end];
				else
					break;
				end -= gap;
			}
			a[end + gap] = tmp;
		}
	}
}

🥝复杂度及稳定性

时间复杂度:O(N^1.3)
空间复杂度:O(1)
稳定性:不稳定。因为预排序很容易就把相同的数的相对顺序打乱了


🍉选择排序

排序思路:
●假设序列最左边、右边下标分别为begin、end
●从序列中找出最大、最小值,并分别将它们放到下标为begin、end的地方
●找出第二大和第二小,分别放到begin+1、end-1
●剩下元素也按照这样排列

在“交换位置”这一步有一个很坑的点,如果最小值刚好在end,那就会和最大值交换位置,但是此时我们的mini仍然在end,直接交换a[mini]和a[begin]就会把最大值和begin处的元素交换位置
所以在最大值和a[end]交换之后检查一下,看mini是否在end处。如果是,就将maxi赋值给mini(因为此时maxi指向的就是最小值)

void SelectSort(int* a, int n) {
	int begin = 0;
	int end = n - 1;
	while (begin < end)
	{
		int mini = begin,maxi = begin;
		for (int i = begin + 1; i <= end; i++)
		{
			if (a[maxi] < a[i])
				maxi = i;
			if (a[mini] > a[i])
				mini = i;
		}
		Swap(&a[maxi], &a[end]);
		if (end == mini)  //让mini重新指向最小值
			mini = maxi;
		Swap(&a[mini], &a[begin]);
		++begin;
		--end;
	}
}

🍌复杂度及稳定性

时间复杂度:第一趟走(n-2)次,第二趟走(n-4)次,第 i 趟走(n-2*i)次……由等差数列公式,可以得出时间复杂度为O(N^2)
空间复杂度:O(1)
稳定性:不稳定。比如1 9 9 4 2 1 3 6,第一趟第一个9就会被换到最后面


🍉堆排序

前面的文章有讲过,升序建大堆,降序建小堆
比如排升序,就建大堆,然后让堆顶元素和堆中最后一个元素交换位置,再进行调整

void HeapSort(int* a, int k) {  //a为给定数组
	for (int i = (k - 1 - 1) / 2; i >= 0; i--) {   //调整为一个堆
		AdjustDown(a, k, i);
	}

	for (int i = k - 1; i >= 0; i--) {  //采用删除结点的思想,先交换,再调整
		Swap(a[0], a[i]);
		AdjustDown(a, i, 0);
	}
}

🍌复杂度及稳定性

时间复杂度:如果有n个数据,那么堆的深度就是logn,最坏情况下,有(n-1)个数据需要调整,所以近似是(n-1)logn,又因为logn的量级比nlogn小,可以忽略,所以时间复杂度就是O(N*logN)
(注意:实际比N * logN略小一些)

上面说“近似”是因为并不是每个数据都要调整logn层,但是由于logn一般不大(参考:2的30次方是10亿多一点,此时logn就是30),它的大小一般就是几十这样子,所以相差这一点对于时间复杂度基本没影响

空间复杂度:O(1)
稳定性:不稳定


🍉写在最后

以上就是本篇文章的全部内容,如果你觉得本文对你有所帮助的话,那不妨点个小小的赞哦!(比心)

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

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

相关文章

Required request body is missing报错及解决

今天&#xff0c;我在尝试调用后端接口展示文章数据时遇到了错误&#xff0c;错误原因是请求体缺失&#xff0c; 但是我明明传了参数 然后我找了很久错误原因&#xff0c;发现在之前跟着写的一个差不多的功能时&#xff0c;请求方式是post 而我写的确是get 将get改为post后&…

【DevOps-06】Jenkins实现CI/CD操作

一、简要说明 基于Jenkins拉取GitLab的SpringBoot代码进行构建发布到测试环境实现持续集成 基于Jenkins拉取GitLab指定发行版本的SpringBoot代码进行构建发布到生产环境实现CD实现持续部署 二、准备Springboot工程 1、IDEA新建工程 2、填写项目工程信息 3、选择Springboot版本…

【MATLAB】EEMD_LSTM神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 EEMD-LSTM神经网络时序预测算法是一种结合了扩展经验模态分解&#xff08;EEMD&#xff09;和长短期记忆神经网络&#xff08;LSTM&#xff09;的时间序列预测方法。 EEMD是一种改进的EM…

Numpy基础

目录&#xff1a; 一、简介:二、array数组ndarray&#xff1a;1.array( )创建数组&#xff1a;2.数组赋值和引用的区别&#xff1a;3.arange( )创建区间数组&#xff1a;4.linspace( )创建等差数列&#xff1a;5.logspace( )创建等比数列&#xff1a;6.zeros( )创建全0数组&…

云消息队列 Kafka 版生态谈第一期:无代码转储能力介绍

作者&#xff1a;娜米 云消息队列 Kafka 版为什么需要做无代码转储 云消息队列 Kafka 版本身是一个分布式流处理平台&#xff0c;具有高吞吐量、低延迟和可扩展性等特性。它被广泛应用于实时数据处理和流式数据传输的场景。然而&#xff0c;为了将云消息队列 Kafka 版与其他数…

C++第四天

定义一个Person类&#xff0c;私有成员int age&#xff0c;string &name&#xff0c;定义一个Stu类&#xff0c;包含私有成员double *score&#xff0c;写出两个类的构造函数、析构函数、拷贝构造和拷贝赋值函数&#xff0c;完成对Person的运算符重载(算术运算符、条件运算…

使用Redis进行搜索

文章目录 构建反向索引 构建反向索引 在Begin-End区域编写 tokenize(content) 函数&#xff0c;实现文本标记化的功能&#xff0c;具体参数与要求如下&#xff1a; 方法参数 content 为待标记化的文本&#xff1b; 文本标记的实现&#xff1a;使用正则表达式提取全小写化后的…

特斯拉被比亚迪拉下神坛,马斯克难改命运岁月不如人

当这个消息浮现在我面前时&#xff0c;我几乎不敢相信眼前所见。比亚迪这个我曾无数次在文章中提及的中国车企&#xff0c;终于在2023年完成了伟大的历史任务——以销量突破特斯拉&#xff0c;站上全球电动车王座的宝座&#xff01; 过去我们都习惯于从欧美日韩那里听说汽车的成…

Go 编程必备:bufio 库的全面指南与实战技巧

Go 编程必备&#xff1a;bufio 库的全面指南与实战技巧 引言bufio 库概览bufio.Readerbufio.Writerbufio.Scanner 深入 bufio.Readerbufio.Reader 的基本使用高级功能应用场景 探索 bufio.Writerbufio.Writer 的基本使用高级功能应用场景 运用 bufio.Scannerbufio.Scanner 的基…

钉钉小程序生态7—企业机器人加互动卡片,改善用户体验的开始!

文章导航 钉钉小程序生态1—区分企业内部应用、第三方企业应用、第三方个人应用 钉钉小程序生态2—区分小程序和H5微应用 钉钉小程序生态3—钉钉扫码登录PC端网站 钉钉小程序生态4—钉钉小程序三方企业应用事件与回调 钉钉小程序生态5—钉钉群机器人消息通知和钉钉工作通知 钉…

React Admin 前端脚手架之ant-design-pro

文章目录 一、React Admin 前端脚手架选型二、React Admin 前端脚手架之ant-design-pro三、ant-design-pro使用步骤四、常用总结&#xff08;持续更新&#xff09;EditableProTable组件 常用组件EditableProTable组件 编辑某行后&#xff0c;保存时候触发发送请求EditableProTa…

Bayes贝叶斯识别Spam Email垃圾邮件

目录 介绍&#xff1a; 一、Gaussian Naive Bayes(连续型变量) 1.1数据处理 1.2建模 1.3cross_val_score函数评估 1.4classification_report函数评估 1.5classification_report函数和cross_val_score函数的区别 二、 Multinomial Naive Bayes&#xff08;离散型变量&…

软件工程专业毕业设计题目怎么选?

文章目录 0 简介1 如何选题2 最新软件工程毕设选题3 最后 0 简介 学长搜集分享最新的软件工程业专业毕设选题&#xff0c;难度适中&#xff0c;适合作为毕业设计&#xff0c;大家参考。 学长整理的题目标准&#xff1a; 相对容易工作量达标题目新颖 1 如何选题 最近非常多的…

[嵌入式C][入门篇] 快速掌握基础(9个语句)

开发环境&#xff1a; 网页版&#xff1a;跳转本地开发(Vscode)&#xff1a;跳转 文章目录 一、基础语法&#xff08;1&#xff09;if (如果)示例1: 普通使用 if示例2: 带否则 else示例3: 否则如果 else if &#xff08;2&#xff09;switch case (选择)规则示例1: &#xff0…

Arduino开发实例-EMG 肌肉信号传感器

EMG 肌肉信号传感器 文章目录 EMG 肌肉信号传感器1、EMG 肌肉信号传感器介绍2、硬件准备及接线3、代码实现1、EMG 肌肉信号传感器介绍 在医学研究中,测量肌肉的活动、收缩和扩张非常重要。 EMG 肌肉传感器测量肌肉活动并产生信号以显示扩张和收缩量。 因此,输出取决于所选肌…

k8s笔记1- 初步认识k8s

k8s简介&#xff1a; kubernetes&#xff0c;俗称k8是&#xff0c;用于自动部署&#xff0c;扩缩和管理容器化应用程序的开源系统&#xff0c;它将组成应用程序的容器&#xff0c;组合成逻辑单元&#xff0c;便于管理和服务发现。 k8s的作用 自动化上线和回滚、存储编排…

听GPT 讲Rust源代码--compiler(9)

File: rust/compiler/rustc_trait_selection/src/traits/select/mod.rs 在Rust源代码中&#xff0c;rust/compiler/rustc_trait_selection/src/traits/select/mod.rs文件的作用是实现Rust编译器的trait选择器。 首先&#xff0c;让我们逐个介绍这些struct的作用&#xff1a; Se…

Boost学习之深入理解asio库

Asio简介 Boost C 库 Asio&#xff0c;它是异步输入输出的核心。 名字本身就说明了一切&#xff1a;Asio 即异步输入/输出。该库可以让 C 异步地处理数据&#xff0c;且平台独立。 异步数据处理就是指&#xff0c;任务触发后不需要等待它们完成。 相反&#xff0c;Boost.Asio …

调用百度地图 API 的步骤详解

百度地图 Web 服务 API 为开发者提供 http/https 接口&#xff0c;即开发者通过 http/https 形式发起检索请求&#xff0c;获取返回 json 或 xml 格式的检索数据。用户可以基于此开发 JavaScript、C#、C、Java 等语言的地图应用。百度地图 API 在线地址为&#xff1a;baidumap.…

Gromacs make_ndx建组问题

1. 选择特定分子或原子&#xff1a; gmx make_ndx -f input.gro -o output.ndx这将打开交互式界面&#xff0c;您可以在其中选择要包含在索引文件中的分子和原子。按照提示进行操作&#xff0c;选择适当的分组。 2. 手动创建索引文件&#xff1a; 您还可以手动创建一个文本文件…