【数据结构】—从直接插入排序升级到希尔排序究极详解(含C语言实现)

news2024/11/17 15:57:04

                                       食用指南:本文在有C基础的情况下食用更佳 

                                       🔥这就不得不推荐此专栏了:C语言

                                       ♈️今日夜电波:透明で透き通って何にでもなれそうで—HaKU

                                                                2:05 ━━━━━━️💟──────── 5:38
                                                                    🔄   ◀️   ⏸   ▶️    ☰ 

                                      💗关注👍点赞🙌收藏您的每一次鼓励都是对我莫大的支持😍 


目录

♉️一、前置知识—什么是插入排序

♊️二、直接插入排序

        直接插入排序的思想

        直接插入排序的实现 

        直接插入排序的效率 

♋️ 三、希尔排序

        希尔排序的思想

        希尔排序的实现 

       ♌️ 希尔排序的效率 


♉️一、前置知识—什么是插入排序

        插入排序的基本思想是将一个待排序的序列逐个插入到已经排好序的序列中,直到全部元素都插入完成每次插入一个元素时,将它与已经排好序的元素逐个比较,找到它在已排好序列中的位置,并插入到该位置。具体实现时,可以将待排序序列分为已排序和未排序两部分,从未排序序列中依次取出元素逐个插入已排序序列中,直到待排序序列为空为止。

         一个形象的🌰:

        日常生活中我们在玩扑克时:将每一张牌都插入到一个有序的位置就是一种插入排序:


♊️二、直接插入排序

        直接插入排序的思想

        其基本思想是将待排序的元素插入到已经有序的序列中,使得插入后的序列仍然有序。

        具体操作步骤如下:

  1. 将第一个元素看作已经排好序的序列。
  2. 依次将后面的元素插入到前面已经排好序的序列中。
  3. 对于未排序的元素,从后往前依次比较,若比前一个元素小则交换位置,直到找到合适的位置插入。
  4. 重复步骤2和3,直到所有元素都插入到已排序的序列中。

        一张经典的插入排序动图让你理解: 

 

        直接插入排序的实现 

        详细见代码内的注释。

void InsertSort(int* a, int n)
{
	// [0,end]有序,把end+1位置的插入到前序序列
	// 控制[0,end+1]有序
	for (int i = 0; i < n - 1; i++)//遍历每一个元素
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (tmp < a[end])//当后一个元素也就是tmp小于前面的某一个元素时先将前一个元素后移
			{
				a[end + 1] = a[end];
			}
			else//只要找到大于tmp的元素,直接跳出,然后插在这个元素后
			{
				break;
			}

			--end;//向前移动操作
		}

		a[end + 1] = tmp;//将要插入的元素也就是最后的元素插入到相应的位置
	}
}

        实现效果:

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

	printf("\n");
}

int main()
{
	
	int arr[] = { 3,44,4,8,547,36,27,2,46,494,19,50,48 };
	Print(arr, sizeof(arr) / sizeof(arr[0]));
	InsertSort(arr, sizeof(arr) / sizeof(arr[0]));
	Print(arr, sizeof(arr) / sizeof(arr[0]));

	return 0;
}

 

        直接插入排序的效率 

        1. 元素集合越接近有序,直接插入排序算法的时间效率越高
        2. 时间复杂度:O(N^2)
        3. 空间复杂度:O(1),它是一种稳定的排序算法
        4. 稳定性:稳定

 


♋️ 三、希尔排序

        希尔排序的思想

        希尔排序通过将待排序的数组按照一定的间隔分组对每组使用插入排序算法进行排序,随着间隔的逐渐缩小,每组包含的元素数量逐渐增多,当间隔缩小至1时,整个序列被分成一组,算法便终止。

        

        希尔排序的步骤如下:

  1. 首先选定一个增量gap,一般设置为数组长度的1/2,之后以gap为步长,将整个数组分为多个子序列(每个子序列长度为gap)。
  2. 对于每个子序列,使用插入排序算法进行排序。
  3. 缩小gap,重复第2步操作,直至gap为1时,整个序列被分成一组,算法终止。

         两张经典的图让你理解:

  

 

        希尔排序的实现 

         详细见代码内的注释。

void ShellSort(int* a, int n)
{
	int gap = n;//首先,计算出最初的步长(通常为数组长度的一半)
	while (gap > 1)
	{
		gap = gap / 2;//对每个步长进行循环,直至步长为1
		//gap = gap / 3 + 1;//还有一种说法是每次除以3的步长,+1是为了保证最后gap==1

		for (int i = 0; i < n - gap; ++i)//前几次为预排序,其实就是步长为gap的插入排序,当gap==1时就是插入排序了
		{
			int end = i;
			int tmp = a[end + gap];//按步长找到后一个元素
			while (end >= 0)
			{
				if (tmp < a[end])//当后一个元素也就是tmp小于前面的某一个元素时先将前一个元素后移
				{
					a[end + gap] = a[end];
				}
				else//只要找到大于tmp的元素,直接跳出,然后插在这个元素后
				{
					break;
				}
				end -= gap;//向前移动操作
			}
			a[end + gap] = tmp;//将要插入的元素也就是最后的元素插入到相应的位置
		}
	}
}

            实现效果: 

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

	printf("\n");
}

int main()
{
	int arr[] = { 9,1,2,5,7,4,8,6,3,5 };
	Print(arr, sizeof(arr) / sizeof(arr[0]));
	ShellSort(arr, sizeof(arr) / sizeof(arr[0]));

	Print(arr, sizeof(arr) / sizeof(arr[0]));

	return 0;
}

        

       ♌️ 希尔排序的效率 

        希尔排序的效率取决于增量序列的选择。较好的增量序列可以使希尔排序比插入排序和选择排序等简单排序算法更加高效,但是对于不同的数据集,效率可能会有所差异。平均时间复杂度为O(n^1.3),最坏时间复杂度为O(n^2)。希尔排序虽然不如快速排序和归并排序等高级排序算法,但是在某些特定场景下具有很好的性能表现。

 


                    感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o! 

                                       

                                                                         给个三连再走嘛~  

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

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

相关文章

干货分享 | 关于同星硬件接口卡及TSMaster软件常见问题QA指南

TSMaster是同星智能开发的一款国产汽车总线工具链软件平台&#xff0c;是全方位汽车总线设计、仿真、分析、诊断和标定的专业工具&#xff0c;支持从需求分析到系统实现的整个系统开发过程。同星智能硬件接口卡可以提供CAN, CAN FD, LIN, FlexRay, 与Ethernet等网络的开发、仿真…

李宏毅-hw7-利用Bert完成QA

一、查漏补缺、熟能生巧&#xff1a; 只有熬过不熟练的时期&#xff0c;反复琢磨&#xff0c;才会有熟练之后&#xff0c;藐视众生的时刻 1.关于transformers中的tokenizer的用法的简单介绍&#xff1a; from transformers import BertTokenizerFast# 加载预训练的BERT模型to…

uniapp Echart X轴Y轴文字被遮挡怎么办,或未能铺满整个容器

有时候布局太小&#xff0c;使用echarts&#xff0c;x轴y轴文字容易被遮挡&#xff0c;怎么解决这个问题呢&#xff0c;或者是未能铺满整个容器。 方法1&#xff1a; 直接设置 containLabel 字段 options: { grid: { containLabel: true, },} 方法2: 间接设置&#xff0c;但是…

微信小程序页面栈超出导致页面卡死

微信小程序页面栈不能超出10个 超出10个之后无法进行点击选择跳转 解决方法&#xff1a; 跳转的时候&#xff0c;判断之前页面栈里是否存在要跳转的页面&#xff0c; 如果存在之前页面&#xff0c;就navigateBack返回之前页面&#xff0c; 如果不存在之前页面&#xff0c;判断…

RocketMQ 核心编程模型以及生产环境最佳实践

文章目录 1、RocketMQ的消息模型2、深入理解RocketMQ的消息模型2.1、RocketMQ客户端基本流程2.2、消息确认机制2.2.1、 发送消息的方式第一种称为单向发送第二种称为同步发送第三种称为异步发送 2.2.2、状态确认机制2.2.3、消费者也可以自行指定起始消费位点 2.3、广播消息2.4、…

nginx 报错[emerg]: unknown directive “锘? in E:\nginx-1.18.0/conf/nginx.conf:3

报错&#xff1a;nginx 报错[emerg] 32408#14080: unknown directive "锘? in E:\nginx-1.18.0/conf/nginx.conf:3 原因&#xff1a;使用nginx服务时&#xff0c;用txt记事本打开编辑了nginx.conf文件&#xff0c;类似WINDOWS自带的记事本等软件&#xff0c;在保存一个以…

mysql触发器triggers

文章目录 1、创建触发器2、 查看触发器3、删除触发器 1、创建触发器 语法&#xff1a; CREATE TRIGGER 触发器名称 BEFORE/AFTER INSERT/UPDATE/DELETE ON 表名 FOR EACH ROW BEGIN SQL逻辑 END;BEFORE 或 AFTER 表示之前 还是 之后触发 INSERT 或 UPDATE 或 DELETE 表示监听…

PostgreSQL 查询某个属性相同内容出现的次数

查询某个数据库表属性 name 相同内容出现出现的次数&#xff0c;并按次数从大到小排序 SELECT name, COUNT(*) AS count FROM your_table GROUP BY name ORDER BY count DESC;示例 select project_id, COUNT(*) AS count from app_ads_positions group by project_id order b…

(WRF/Chem)在大气环境领域实践技术应用

随着我国经济快速发展&#xff0c;我国面临着日益严重的大气污染问题。近年来&#xff0c;严重的大气污染问题已经明显影响国计民生&#xff0c;引起政府、学界和人们越来越多的关注。大气污染是工农业生产、生活、交通、城市化等方面人为活动的综合结果&#xff0c;同时气象因…

智能报修管理系统的作用和功能

智能报修管理系统针对不同的服务对象、不同的服务内容、不同的紧急情况&#xff0c;不同的区域&#xff0c;自定义设定响应指标&#xff0c;承诺客户在多长时间内响应或是解决问题&#xff0c;保障服务质量。随着报修、后勤、运维等规模日趋庞大&#xff0c;许多单位每日需处理…

echarts-根据数据大小实现折线渐变色

先看示例图&#xff1a; 这几年一直在做大数据可视化前端开发&#xff0c;接下来把近几年用到的比较经典案例给大家分享下&#xff0c;主要用到的可视化库为Echarts、Threejs、Element、D3、fabricjs等。 这个案例是Echarts&#xff0c;Echarts算是学习成本比较低的一个很好的…

Java下打印一个等腰三角型

想达到这个结果&#xff0c;通常的做法是通过拼结两个三角型达到&#xff0c;但是实际上还有最右边的第三个三角型没有处理&#xff0c;这个拼结的方法总让人看起来有一点不完美的感觉&#xff0c;于是我自创了一个思路&#xff0c;一气合成&#xff0c;代码如下&#xff08;本…

想要提高客户留资率?一个留资机器人就够了!

随着移动互联网进入“下半场”&#xff0c;用户在线参与率持续上升&#xff0c;导致企业的获客成本不断攀升。特别是近年来新型营销场景如直播销售、内容推广和短视频引流等的不断涌现&#xff0c;企业在多个渠道和平台上的广告支出激增&#xff0c;试图吸引更多潜在客户。然而…

提升开发效率的低代码思路

目录 一、低代码如何快速开发&#xff1f; 1.可视化开发 2.预构建的组件和模板 3.集成的开发和测试工具 4.跨平台兼容性 5.可伸缩性和可扩展性 二、前后端分离的开发框架 技术架构 部署方式 应用入口 三、小结 低代码开发工具正在日益变得强大&#xff0c;它正不断弥合着前后端…

咨询电商平台API的调用方法!

一、引言 随着电子商务的快速发展&#xff0c;电商平台间的竞争愈加激烈。为了提供更加优质的服务&#xff0c;很多电商平台会开放其商品API数据&#xff0c;允许第三方开发者利用这些数据创建各种应用。本文将对商品API数据的概念、获取方式以及在电商中的应用进行探讨&#…

laravel 阿里云短信发送

示例 一、安装 安装&#xff1a;composer require mrgoon/aliyun-sms dev-master 二、打开config/app.php&#xff0c;添加配置代码 1、‘providers’ 配置组下添加 Mrgoon\Aliyunsms\AliyunsmsServiceProvider::class, 2、‘aliases’ 配置组下添加 Aliyunsms>Mrgoon…

【计算机网络 - 自顶向下方法】计算机网络和因特网

目录 1. What is the Internet? 1.1 因特网的具体构成 1.2 因特网的功能 2. Network core 2.1 基本介绍 2.2 分组交换 2.2.1 序列化时延 2.2.2 排队延迟和丢包 2.2.3 分组交换的优缺点 2.3 电路交换 2.3.1 基本概念 2.3.2 电路交换网络中的复用 2.3.3 电路交换文件…

vue3 封装公共弹窗函数

前言&#xff1a; 博主封装了一个公共弹窗函数接收四个参数&#xff0c;&#xff08;title&#xff1a;弹窗标题, ContentComponent&#xff1a;弹窗中显示的组件内容, opt&#xff1a;接收弹窗本身的属性和props, beforeSure&#xff1a;点击确定做的操作&#xff08;请求后端…

《动手学深度学习 Pytorch版》 7.3 网络中的网络(NiN)

LeNet、AlexNet和VGG的设计模式都是先用卷积层与汇聚层提取特征&#xff0c;然后用全连接层对特征进行处理。 AlexNet和VGG对LeNet的改进主要在于扩大和加深这两个模块。网络中的网络&#xff08;NiN&#xff09;则是在每个像素的通道上分别使用多层感知机。 import torch fr…