带你学懂数据结构中的八大排序(上)

news2024/10/6 20:39:48

✨个人主页: Yohifo
🎉所属专栏: 数据结构 | C语言
🎊每篇一句: 图片来源

  • Every challenge, every adversity, contains within it the seeds of opportunity and growth.
    • 每个挑战,每次逆境,里面都藏有机会与成长的种子。

道阻且长,行则将至


文章目录

  • 📘前言
  • 📘正文
    • 📖插入排序
      • 📃直接插入排序
      • 📃希尔排序
    • 📖选择排序
      • 📃简单选择排序
      • 📃堆排序
    • 📖排序小结
  • 📘总结


📘前言

排序(Sort)是初阶数据结构中的最后一块内容,所谓排序,就是通过某种手段,使目标数据变为递增或递减,排序有很多种方式:插入、选择、交换、归并、映射 等等,本文会介绍这些方式下的详细实现方法,因篇幅较长,故分为上下文的形式介绍,本文是上半部分。

下面是通过排序生成的排行榜

TIOBE编程语言排行榜


📘正文

📖插入排序

插入,指将数据插入到合适位置,这个分类中包含了两种排序算法:直接插入希尔,其中希尔排序又称缩小增量排序,是一种非常快但不稳定的排序,它的时间复杂度计算极为复杂,下面详细来看看这两个排序吧

📃直接插入排序

思路:从第二个数开始,假设此数为 tmp ,逐个往前进行比对,如果前数大于 tmp ,就将前数值赋值到 tmp 处,然后继续往前比对,直到找到小于或等于 tmp 的数(或者比对至数据首)就停止,最后将 tmp 的值赋值到此处就行了

//直接插入排序
void InsertSort(int* pa, int n)
{
	assert(pa);

	//从后往前比较,找到合适位置就插入
	for (int i = 1; i < n; i++)
	{
		int end = i;
		int tmp = pa[end];
		while (end)
		{
			if (pa[end - 1] > tmp)
				pa[end] = pa[end - 1];
			else
				break;
			end--;
		}
		pa[end] = tmp;
	}
}

动图展示
直接插入排序

时间复杂度:

  • 最坏:数据为一个逆序的等差数列 O(N^2)
  • 最好:顺序有序 O(N)

空间复杂度:

  • 仅仅只需要一个 tmp 变量 O(1)

稳定性:

  • 稳定,当两个相同数相遇时,后者是不会跑到前者前面去的

📃希尔排序

希尔排序是在直接插入排序上进行优化的一种排序,希尔排序分为两步:

  • 1、预排序,使得数据尽可能接近有序
  • 2、直接插入排序,最后调用一次直接插入排序,快速的完成排序

思路:预排序是通过区间划分实现的,假设当前区间为 gap,那么 1、1+gap*n 可以分成一组,同理2、3、4 都可以分,将这些组分别进行直接插入排序(数据少,效率高)。每完成一次分组排序,gap 就会缩小,直到 gap 为1时,进行一次直接插入排序,整个希尔排序就完成了

//希尔排序
void ShellSort(int* pa, int n)
{
	assert(pa);

	//思路:在插入排序的基础上,先分为n个区间,使数组尽可能有序(预排序)
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;	//确保gap最后为1
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = pa[end + gap];
			while (end >= 0)
			{
				//此时的end位于tmp之前s
				if (pa[end] > tmp)
					pa[end + gap] = pa[end];
				else
					break;

				end -= gap;
			}

			pa[end + gap] = tmp;
		}
	}
}

动图展示(图太长了,分段展示)
1、预排序
希尔排序(预排序)
2、直接插入排序
直接插入排序

时间复杂度:

  • 希尔的时间复杂度计算是一个极其复杂的过程,需要用到高等数学的知识,这里直接记就行 O(N^1.3)

空间复杂度:

  • 仅仅只需要一个 tmp 变量 O(1)

稳定性:

  • 不稳定,当两个相同数被不同区间选中时,可能会发生交换现象,示例 1 4 2 2 3

📖选择排序

选择排序下也可以分为两种:简单选择与之前学过的堆排序,两者的本质是一样的,都是依赖于不断的比对,选到合适数后进行交换

📃简单选择排序

思路:选到最大的数,然后与 end 值交换;优化:选最大与最小,分别与 end 值和 begin 值交换

void swap(int*pnum1, int* pnum2)
{
	assert(pnum1 && pnum2);

	int tmp = *pnum1;
	*pnum1 = *pnum2;
	*pnum2 = tmp;
}

//简单选择排序
void SelectSort(int* pa, int n)
{
	assert(pa);

	//思路:选最小的放前面,选最大的放后面
	int begin = 0;
	int end = n - 1;
	while (begin < end)
	{
		int maxi = begin;
		int mini = begin;

		for (int i = begin + 1; i <= end; i++)
		{
			if (pa[i] > pa[maxi])
				maxi = i;
			if (pa[i] < pa[mini])
				mini = i;
		}
		swap(&pa[begin], &pa[mini]);
		if (maxi == begin)
			maxi = mini;

		swap(&pa[end], &pa[maxi]);

		begin++, end--;
	}
}

动图展示:
简单选择排序

时间复杂度:

  • 这是一个比较糟糕的排序,因为不管是什么情况都是 O(N^2)

空间复杂度:

  • 仅借助变量辅助交换 O(1)

稳定性:

  • 不稳定,在选择时,可能把相同数中的后者选到前面,示例 1 4 2 2 3

注意:

  • 当交换 min 值与 begin 值后,如果 max 等于此时的 begin ,那么就要将 max 赋为 min,即 max = min

📃堆排序

思路:堆排序用到了堆的知识,如果想排升序的话建大堆,因为大堆中堆顶是最大值,将堆顶值与堆低值交换后,执行向下调整,使其再次变为大堆,就这样反复交换、调整,堆排序就完成了

void swap(int*pnum1, int* pnum2)
{
	assert(pnum1 && pnum2);

	int tmp = *pnum1;
	*pnum1 = *pnum2;
	*pnum2 = tmp;
}

void AdjustDown(int* pa, int n, int parent)
{
	assert(pa);

	//大堆,找大孩子,调整
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && pa[child + 1] > pa[child])
			child++;

		if (pa[child] > pa[parent])
		{
			swap(&pa[child], &pa[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
			break;
	}
}

//堆排序
void HeapSort(int* pa, int n)
{
	assert(pa);

	//思路:升序建大堆,将堆顶元素沉底,然后再调整
	int parent = (n - 1 - 1) / 2;	//找父亲
	for (int i = parent; i >= 0; i--)
		AdjustDown(pa, n, i);

	//将堆顶元素沉底后调整
	int end = n - 1;
	while (end > 0)
	{
		swap(&pa[0], &pa[end]);
		AdjustDown(pa, end--, 0);
	}
}

动图展示:
1、调整建堆
建堆
2、向下调整排序(上)
排序主体,上
3、向下调整排序(下)
排序主体,下

时间复杂度:

  • 向下调整+交换 O(N*logN)

空间复杂度:

  • 仅借助变量辅助交换 O(1)

稳定性:

  • 不稳定,当两个相同值分别位于首尾时,向下调整会打乱相对顺序,示例 2 4 1 3 2

📖排序小结

排序名称时间复杂度空间复杂度稳定性
直接插入排序O(N^2)O(1)稳定
希尔排序O(N^1.3)O(1)不稳定
简单选择排序O(N^2)O(1)不稳定
堆排序O(N*logN)O(1)不稳定

更多排序将在下篇文章中讲解


📘总结

排序有很多种,有好的、有坏的,我们要重点掌握优秀的排序,比如希尔堆排,当前其他排序的思想也得清楚,知道怎么实现就行了。本文只是排序的上半部分,涉及的排序都还算简单,下一篇文章中将会介绍排序大哥:快排,以及同样优秀的归并排序,知识点很难,但也很重要,敬请期待吧

如果你觉得本文写的还不错的话,期待留下一个小小的赞👍,你的支持是我分享的最大动力!

如果本文有不足或错误的地方,随时欢迎指出,我会在第一时间改正

星辰大海

相关文章推荐
关于“堆”,看看这篇文章就够了(附堆的两种应用场景)
听说你还不了解二叉树?赶紧进来轻松解决
听说Linux基础指令很多?这里都帮你总结好了

感谢支持

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

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

相关文章

山外山在科创板上市:市值约47亿元,高光勇为实际控制人

12月26日&#xff0c;重庆山外山血液净化技术股份有限公司&#xff08;下称“山外山”&#xff0c;SH:688410&#xff09;在上海证券交易所科创板上市。本次上市&#xff0c;山外山的发行价格为32.30元/股&#xff0c;发行市盈率为297.74倍。 据贝多财经了解&#xff0c;山外山…

vivo 低代码平台【后羿】的探索与实践

作者&#xff1a;vivo 互联网前端团队- Wang Ning 本文根据王宁老师在“2022 vivo开发者大会"现场演讲内容整理而成。公众号回复【2022 VDC】获取互联网技术分会场议题相关资料。 本文主要从前后端分离的低代码方案、自研高性能渲染引擎、高效的可视化配置方案、千亿级内容…

基于yolov5s实践国际象棋目标检测模型开发

在我前面的一篇文章中讲解实现了基于改进的yolov5s-spd模型实现了五子棋目标对象检测模型系统的设计开发&#xff0c;这里紧接前文&#xff0c;突发奇想&#xff0c;是否可以借鉴同样的思路实现象棋的检测模型开发呢&#xff1f;理论上面肯定是可以的&#xff0c;但是实际效果如…

FineReport企业报表-配置MySQL8外接数据库(2)

1. 配置外接数据库 1.1 外接数据库配置入口 外接数据库的配置入口&#xff0c;有三种形式&#xff1a; 1&#xff09;超级管理员第一次登录数据决策系统时&#xff0c;即可为系统配置外接数据库。如下图所示&#xff1a; 2&#xff09;对于使用内置数据库的系统&#xff0c;管…

burpsuite——身份验证

文章目录通过不同响应枚举用户名2FA 简单旁路密码重置破坏逻辑通过细微不同的响应枚举用户名通过响应计时的用户名枚举破解暴力保护&#xff0c;IP 封锁通过帐户锁定的用户名枚举2FA 破坏逻辑暴力破解保持登录状态的 cookie通过不同响应枚举用户名 就是所谓的暴力破解&#xff…

如何将高程数据转成南方CASS的DAT格式

需要的工具 BIGEMPA GIS Office 下载地址&#xff1a;http://download.bigemap.com/bmsetup.rar 第一步&#xff1a;将下载好的高程数据DEM直接拖到global mapper中(如何下载高程DEM&#xff1f;)&#xff0c;如下图所示&#xff1a; 第二步&#xff1a;将DEM数据保存为高程点…

A - No Majority(DP 动态规划)[AtCoder Grand Contest 060]

题目如下&#xff1a; 思路 or 题解&#xff1a; 对于一个子串&#xff0c; 如果长度为 lenlenlen, 如果该子串中任意一个字符的出现个数 大于 len2\frac{len}{2}2len​ 那该字符串为 UngoodUngoodUngood 串 反之&#xff0c;如果任意子串&#xff0c; 长度设为 lenlenlen, 如…

Map接口-HashMap、Hashtable和Properties

1.Map 接口和常用方法 1.1Map 接口实现类的特点 [很实用] 注意:这里讲的是JDK8的Map接口特点 1)Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value。 Map 中的key 和 value可以是任何引用类型的数据&#xff0c;会封装到HashMap$Node对象中。&#xff08;Node…

公网远程连接内网MySQL数据库【内网穿透】

作为网站运行必备组件之一的数据库&#xff0c;免不了随时对其进行管理维护。若我们没有在安装数据库的电脑旁&#xff0c;但又需要立即对数据库进行管理时&#xff0c;应该如何处理&#xff1f;这时我们可以使用cpolar对内网进行穿透&#xff0c;远程管理和操作MySQL数据库。现…

javaee之spring3

模拟一个银行转账事务 先来看一下基础文件 先来看这个spring中的bean.xml配置文件 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XML…

Dragonfly 和 Nydus Mirror 模式集成实践

文&#xff5c;戚文博 &#xff08;花名&#xff1a;百蓦&#xff09; Dragonfly Maintainer蚂蚁集团软件工程师 主要负责「基于 P2P 的文件以及镜像加速系统」。 本文 2175 字 阅读 15 分钟 PART. 1 背景 自 17 年开源以来&#xff0c;Dragonfly 被许多大规模互联网公司选…

C++贪吃蛇游戏开发实践

C贪吃蛇游戏开发实践 对象分析 我们首先需要确定一个像素点组成的地图&#xff08;画布&#xff09;&#xff0c;要确定行数、列数和像素点大小。这个地图上将会有两个对象&#xff1a;蛇和食物。 蛇由头和身子组成&#xff0c;他们都有自己的位置&#xff0c;所以考虑使用位置…

移动端测试必备技能: adb命令和抓包

移动端测试 是指对移动应用进行的测试&#xff0c;即实体的特性满足需求的程度&#xff0c;进行测试前需要搭建测试环境。 1 移动端自动化环境搭建 1.1 java安装 java JDK 安装jdk-8u181-windows-x64.exe 配置环境变量&#xff1a; JAVA_HOME&#xff1a;D:\developer to…

基于C#+SqlServer开发(WinForm)学生宿舍管理系统【100010056】

学生宿舍管理系统 一、前言 学生宿合是学生们最为熟悉的领域&#xff0c;假定学校有若干栋宿会楼&#xff0c;每栋宿合楼有若干层&#xff0c;每层有若干个寝室&#xff0c;每个寝室可住若干个学生。以往的手工操作已经不能适应现在办公的需要.为了摆脱繁琐的劳动,提高工作效…

HTML XHTML HTML5区别

文章目录HTML & XHTML & HTML5区别HTMLXHTMLHTML5区别HTML & XHTML & HTML5区别 HTML HTML&#xff0c;全称“HyperText Mark-up Language&#xff08;超文本标记语言&#xff09;”&#xff0c;它是构成网页文档的主要语言。我们常说的HTML&#xff0c;指的…

金融服务机构提高移动应用程序安全性的 3 种方式

金融移动应用程序的使用正在迅速加速&#xff0c; 2020 年用户会话数量增长了 49% 。VMware报告称&#xff0c;金融应用程序的网络攻击在同年也增长了 118%。 Intertrust的另一份报告显示&#xff0c;77% 的金融服务应用程序至少包含一个可能导致数据泄露的安全漏洞。最近发现…

【Three.js入门】纹理加载进度、环境贴图、经纬线映射贴图与高动态范围成像HDR

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;也会涉及到服务端 &#x1f4c3;个人状态&#xff1a; 在校大学生一枚&#xff0c;已拿多个前端 offer&#xff08;秋招&#xff09; &#x1f680;未…

VMwareLinux详细安装步骤

一、VmWare虚拟机的安装 目录 一、VmWare虚拟机的安装 1、安装虚拟机 二、在虚拟机上安装CentOS 1、创建新虚拟机 2、选择典型→ 下一步 3、选择稍后安装操作系统 4、选择操作系统和版本 5、输入虚拟机名称和安装路径 6、设置磁盘大小 7、选择CentOS安装镜像文件 8、…

射线检测中的像质计

像质计&#xff0c;透度计 Image Quality Indicators&#xff0c;Penetrameters 分类&#xff1a;线型像质计、阶梯孔型像质计、平板孔型像质计、双丝型像质计。 前三种像质计的作用&#xff1a;测定检测图像的厚度&#xff08;密度&#xff09;对比度&#xff1b; 后一种像质…

数论专题(1)数论函数,整数分块

从今天起,我们将要开始数论的学习,是不是感觉很难?难的话就听我讲吧,讲了后就不难了(bushi) 数论函数定义 (数论函数) 数论函数的定义:在全体正整数&#xff08;或者整数&#xff09;上定义的函数称作数论函数。 积性的定义&#xff1a;若 gcd(a,b)1,则f(ab)f(a)f(b)。举个栗…