数据结构之排序【直接插入排序和希尔排序的实现及分析】

news2024/12/29 9:41:47

引言:

今天天气还是依然的冷,码字越来越不容易了,本来上次写了一个比较好的引言,但是因为电脑第二天没电,并且我没有保存,现在找不到了,所以今天我们的引言就这样吧!今天给大家介绍一下有关数据结构中的排序的内容,因为来不及一口气把所有的排序学完并且学明白,我们就把这些排序给分开进行讲解。所以今天我们学的是直接插入排序和希尔排序相关的知识分析和代码的实现。

1.排序的概念及其应用

1.1 排序的概念
排序:所谓的排序就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作
稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],并且r[i]在r[j]之前,而在排序后的序列中,r[i]任然在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的
内部排序:数据元素全部在内存中的排序。
外部排序:数据元素太多不能同时放在内存中,根据排序的过程的要求不能在内存之间移动数据的排序

1.2 排序的应用(此时就可以去淘宝上截图一下,就是价格的排序之类的)(可以很好的充当一个筛选的作用)

1.3 常见的排序:插入排序(直接插入排序、希尔排序) 选择排序(选择排序、堆排序) 交换排序(冒泡排序、快速排序)归并排序

2.直接插入排序的实现及分析

2.1 基本思想:
直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按期关键码值的大小逐个插入到一个已经排好的有序序列中,直到所有的记录插入完为止,然后就得到一个新的有序序列。

2.2 生活中的实例:我们玩扑克牌的时候,就是用了插入排序的思想,如图:
在这里插入图片描述

2.3 具体的实现原理:当我们想要插入第i(i>=1)个元素时,前面的arr[0],arr[1],arr[2],……,arr[i-1]已经排好序,此时用arr[i]的排序码值与arr[i-1],arr[i-1],……,的排序码值进行比较,找到合适的位置将arr[i]插入,原来位置上的元素按照顺序向后移动

2.4 具体代码的实现(最详细的注释)

void InsertSort(int* arr, int n)
{
	//此时这种排序方法是有要求的,比如一定是要要求这个数组中的元素已经是有序的了(所以此时我们排序是在默认这个数组有序的情况下进行的)
	//此时将这个问题拆分一下(变成小问题来解决)
	
	//拆分原理:(关键)此时假设[0,end]中的元素已经是有序的了,然后我们把我们想要插入的元素放在end+1的位置然后按照顺序插入进去,然后使[0,end+1]整个数组也有序(并且此时假设都是以升序来进行的排序)
	int i = 0;
	for (i = 0; i < n - 1; i++)//此时这个位置我们控制成了n-1,但我们要知道次数是到n-2就会结束的(并且此时因为下标的原理,此时这样写就是刚好,不然就会导致end+1的位置造成越界)
	{
		//这个for循环就是为了控制(end ,控制了end也就是控制了有顺序的元素的个数)插入的元素的个数(此时有了这个for循环就可以使我想插入几个元素就比较几次),显而易见,下面的那个while循环只是为了控制顺序插入一个数据(而此时有了这个for循环就可以使我顺序插入n个数据了)
		//int end;//此时就是假设,我也不知道此时的end是什么东西,唯一知道的就是[0,end]此时是一个有序的数组
		//此时想要控制插入的元素的个数,那么此时就可以知道end的值了,所以要对end进行初始化,所以就不可以按照上面那样写了,下成下面这个样子就行
		int end = i;
		int tmp = arr[end + 1];//此时为了进行排序,会进行位置的移动,所以为了防止end+1位置被覆盖,所以此时我可以把我的end+1的位置给先存起来(以便于待会可以更好的拿出来使用)
		while (end >= 0)//此时进行码值的比较的时候(会有一个特殊的情况:就是我想要插入的元素的码值比数组中的元素的码值都要小),所以此时我就要比较很多次,假如比end=0元素的值都要小,此时end再减减,就会导致end=-1,所以此时就会导致越界访问,所以此时我们这个循环就一定要把这个比较的次数(也就是end--)给控制好,让其不为<0,所以此时这个循环的条件就是end>=0,才进行元素的调换
		{
			if (arr[end] > tmp)//此时的这个tmp就是表示我要插入的值(并且此时这个我要插入的值就是在end+1,这个数组的位置处),所以我此时就可以进行比较码值的大小,这样就可以把我想要排序的元素按照顺序从end+1的位置插入到他合适的位置处
			{
				arr[end + 1] = arr[end];//这个位置就是进行排序嘛,就是码值的比较,然后我要排序的元素此时就可以从数组中的最后一个位置慢慢的移动到我的合适的位置
				end--;//这个end--的意思就是慢慢的向前走的意思,直到找到合适的位置或者走到数组的最前面(也就是end=0的位置)(这样我就可以跟数组中的所有元素进行比较了)
			}
			else
			{
				//此时这个else的意思是显而易见的:就是我想要插入的元素比数组中的元素的码值大了,此时就可以直接进行插入了
				//但是此时这个直接插入在这个位置就有一个小细节(还是当我想要插入的元素的码值比我数组中的都小的时候出现的情况),因为当我想插入的数据是最小的时候,程序来到这个位置就会导致我数组中的元素每个都往后移动了一位,然后此时就导致end--,导致此时的end变成了-1,因为我刚刚的end还是0吗,符合循环的条件(但是最后一次减减才导致的-1),所以此时如果程序来到这个位置,此时的end就是还是-1,所以在这个位置插入元素就又会导致越界的问题了,所以此时这个else并不适合插入数据
				break;//所以这个else只适合用break跳出去
			}
		}
		//并且此时程序来到这个位置就是说明循环不满足条件或者是else中的break起了作用,所以此时这个位置就可以放心的把我的数据给插入到这个数组之中去了
		arr[end + 1] = tmp;//因为end+1就可以防止end=-1的情况,并且也符合正常的元素的比较后的插入(就是在这个元素的后一个位置插入,也就是数组中的end+1的位置)

	}
}

2.5 直接插入排序的测试

void PrintArr(int* arr, int sz)
{
	int i;
	for (i = 0; i < sz; i++)
	{
		printf("%d ",arr[i]);
	}

	printf("\n");

}

void TestInsertSort()
{
	int arr[] = { 6,3,7,4,10,9,2,1,5,8 };
	InsertSort(arr, sizeof(arr) / sizeof(arr[0]));
	PrintArr(arr, sizeof(arr) / sizeof(arr[0]));

}

#include<stdio.h>
int main()
{
	TestInsertSort();

	return 0;
}

在这里插入图片描述

3.希尔排序的实现及分析

希尔排序又称为缩小增量法。

3.1 希尔排序的基本思想:先选定一个整数,把待排序文件中所有记录分成一个组,所有距离为1的记录在用一个组内,并对每一组的记录进行排序。然后,取,重复上述分组和排序的工作。当到达距离=1时,所有记录在统一组内排好序。
就是一个直接插入排序的优化(但是好像很高级)
此时这个希尔排序进行排序是将排序过程分为了两步
3.1.1.先进行预排序,让数组接近有序
3.1.2.然后再进行直接插入排序

3.2 此时就会涉及到一个叫gap的变量,我们可以对数组中间隔为gap的元素先进行一个预排序,gap由大变小。
特点:gap越大,大的数可以越快的到后面,小的数可以越快的到前面,gap越小,越接近有序,gap=1时就是我的直接插入排序
在这里插入图片描述

代码实现:(具体原理就是直接插入排序的原理,重点就是如何理解这个gap)

void ShellSort(int* arr, int n)
{
	//int gap = 3;//因为我并不知道我需要排序的数据的个数,所以这个位置我们不可以将gap给固定掉
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 2;
		//gap = gap / 3 + 1;//这两种都可以
		//此时这个位置中gap>1就都是预排序
		//gap==1时就是直接插入排序
	}
	int i = 0;
	//此时下面的代码就是为了把数组中间隔为gap的多组数据同时进行排序
	for (i = 0; i < n - gap; i++)
	{
		int end = i;
		int tmp = arr[end + gap];
		while (end >= 0)
		{
			if (arr[end] > tmp)
			{
				arr[end + gap] = arr[end];
				end = end - gap;
			}
			else
			{
				break;
			}
		}
		arr[end + gap] = tmp;

	}

}

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

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

相关文章

Zookeeper 4 Zookeeper JavaAPI 操作 4.3 Curator API 常用操作【添加节点】

Zookeeper 【黑马程序员Zookeeper视频教程&#xff0c;快速入门zookeeper技术】 文章目录Zookeeper4 Zookeeper JavaAPI 操作4.3 Curator API 常用操作4.3.1 添加节点4 Zookeeper JavaAPI 操作 4.3 Curator API 常用操作 4.3.1 添加节点 直接开始编写 测试方法 先写一下&a…

Web入门开发【五】- 线上部署

欢迎来到霍大侠的小院&#xff0c;我们来学习Web入门开发的系列课程。 首先我们来了解下这个课程能学到什么&#xff1f; 1、你将可以掌握Web网站的开发全过程。 2、了解基础的HTML&#xff0c;CSS&#xff0c;JavaScript语言。 3、开发自己的第一个网站。 4、认识很多对编…

南卡与JBL蓝牙耳机哪款比较好?数码资深玩家带你深度评测了解

马上到来2023新的一年&#xff0c;不会还有人使用传统有线耳机吧&#xff1f;那你就属最落后的那位了&#xff0c;随着生活水平的提高&#xff0c;科技的快速发展&#xff0c;有线耳机逐渐被真无线蓝牙耳机所取代。现在走在马路上都能看见许多人佩戴着耳机&#xff0c;然而&…

机器学习 | 朴素贝叶斯

一.基本原理 基于条件独立的假设&#xff0c;先计算输入和输出的联合概率密度&#xff0c;然后根据所输入的x计算y的概率&#xff0c;然后选择具有最大后验概率的类作为它的类别 二.优缺点 优点 小规模数据集表现好&#xff0c;适合多分类对于在小数据集上有显著特征的相关对…

Scikit-network-02:载图

载图 在Scikit网络中&#xff0c;图形由其scipy的压缩稀疏行格式中的邻接矩阵&#xff08;或二部图矩阵&#xff09;表示。在本教程中&#xff0c;我们提供了一些方法来实例化此格式的图。 from IPython.display import SVGimport numpy as np from scipy import sparse impo…

SQL注入渗透与攻防(九)之布尔盲注

目录 1.什么是布尔盲注&#xff1f; 2.如何进行布尔盲注&#xff1f; 案列演示&#xff1a; 1.什么是布尔盲注&#xff1f; Web的页面的仅仅会返回True和False。那么布尔盲注就是进行SQL注入之后然后根据页面返回的True或者是False来得到数据库中的相关信息。 我们这里拿sql…

15Python文件操作

文件处理 01. 文件的概念 1.1 文件的概念和作用 计算机的 文件&#xff0c;就是存储在某种 长期储存设备 上的一段 数据长期存储设备包括&#xff1a;硬盘、U 盘、移动硬盘、光盘… 1.2 文件的存储方式 在计算机中&#xff0c;文件是以 二进制 的方式保存在磁盘上的 文本…

论文理解--DEEP COMPRESSION

原文链接&#xff1a; https://github.com/mit-han-lab/amc/security https://zhuanlan.zhihu.com/p/108096347 https://zhuanlan.zhihu.com/p/510905067 摘要 结论&#xff1a; 1、deep compression:由三阶段pipeline组成&#xff1a;pruning(剪枝)、 trained quantilization…

452页24万字智慧城市顶层设计及智慧应用解决方案

智慧城市总体设计 2.1 智慧城市核心技术 2.1.1 物联网 智慧城市是一个有机结合的大系统&#xff0c;涵盖了更透切的感知、更全面的互连&#xff0c;更深入的智能。物联网是智慧城市中非常重要的元素&#xff0c;它侧重于底层感知信息的采集与传输&#xff0c;城市范围内泛在网方…

无需调用Tecplot,PFC后处理技巧为你plot精美科研图

导读&#xff1a;PFC提供了非常美观的可视化处理的窗口—plot&#xff0c;用户可以在这里对模型的运行状态进行检查&#xff0c;也可以将Plot中的视图输出进行处理。一般来说plot中的图片质量足够用于常规的论文配图&#xff0c;当然用户也可以导出数据到tecplot中进行后处理&a…

【UE4 第一人称射击游戏】08-使用“AK47”发射子弹

上一篇&#xff1a; 【UE4 第一人称射击游戏】07-添加“AK47”武器 本节效果&#xff1a; 步骤&#xff1a; 1.在“Blueprints”文件夹内添加一个Actor蓝图&#xff0c;命名为“Projectile_Base”&#xff0c;该蓝图用于表示子弹 双击打开“Projectile_Base”&#xff0c;添加…

期货开户的身份识别验证

无论你是开通商品期货、原油期货还是股指期货以及期权&#xff0c;现在都支持网上办理&#xff01;原油期货和股指期货以及期权品种都是在商品期货账户的基础上满足条件后再另外开通交易权限。叁格期权小编在这里为各位投资者详细介绍商品期货网上开户流程。 一、开户前准备 …

文件透明加密,保护重要数据的安全性

各种泄露事件使人们对信息安全问题的高度关注&#xff0c;随着加密技术的不断完善&#xff0c;主流透明加密技术被广泛应用于企业加密软件中。那么&#xff0c;这个技术如何保护电脑&#xff1f;有什么优点&#xff1f; 文件透明加密是最近几年发展出来的一种文件加解密技术。所…

RK3568平台开发系列讲解(工具命令篇)vim 编辑器的使用

🚀返回专栏总目录 文章目录 一、vim 编辑器有三种模式二、vim 编辑器移动光标三、vim 编辑器支持快速定位四、vim 编辑器的文本的复制和粘贴五、vim 编辑器使用快捷键来复制六、vim 编辑器的删除七、vim 编辑器的撤销八、vim 编辑器的查找九、vim 编辑器的替换十、vim 编辑器…

四、GradCAM可解释性分析——可解释性机器学习(DataWhale组队学习)

目录CAM算法回顾CAM算法流程CAM算法的精妙之处CAM算法的缺点GradCAMGrad-CAM算法的优点&#xff1a;Grad-CAM算法的缺点&#xff1a;Grad-CAM算法的改进Grad-CAM算法Score-CAM算法LayerCAM算法总结CAM算法回顾 CAM算法流程 输入原始图像&#xff0c;经过多层无池化的全卷积神经…

23种设计模式:单例设计模式(饿汉式 VS 懒汉式)

23种设计模式&#xff1a;单例设计模式&#xff08;饿汉式 VS 懒汉式&#xff09; 每博一文案 世事浮沉&#xff0c;有太多的责任需要我们担当&#xff0c;生活中总有些挫折和磨难&#xff0c;让我们觉得快要杠不住了。 但当我们咬牙坚持过那段难熬的时光后&#xff0c;发现并…

居家防护类设备的智能化解决方案

疫情防控政策优化后&#xff0c;你期待的消费暴涨如期而至了吗&#xff1f;近期&#xff0c;继自带“玄学”光环的黄桃罐头被疯抢之后&#xff0c;橘子水、葱姜水、古法掐喉咙消肿等缓解疼痛的“东方神秘法宝”再现各大视频平台。 面对此次居家隔离&#xff0c;哪些产品将再次…

(Java)欢乐的跳

欢乐的跳一、题目描述二、输入格式三、输出格式四、样例&#xff08;1&#xff09;样例输入1&#xff08;2&#xff09;样例输出1&#xff08;3&#xff09;样例输入2&#xff08;4&#xff09;样例输出2五、提示六、正确代码七、注意点以及思路&#xff08;1&#xff09;注意点…

【万字长文】从Linux零拷贝深入了解Linux I/O

前言 存储器是计算机的核心部件之一&#xff0c;在完全理想的状态下&#xff0c;存储器应该要同时具备以下三种特性&#xff1a; 速度足够快&#xff1a;存储器的存取速度应当快于 CPU 执行一条指令&#xff0c;这样 CPU 的效率才不会受限于存储器容量足够大&#xff1a;容量…

新闻发布系统的设计与实现/新闻管理系统

摘要 21世纪是信息的时代&#xff0c;是网络的时代&#xff0c;进入信息社会高速发展的时代&#xff0c;数字化革命给所有领域带来新的改变。传统的报纸杂志已经远远满足不了人们的需求&#xff0c;人们更加希望于能够在网上了解更多的新闻和信息&#xff0c;网页逐渐融入人们的…