希尔排序-C语言版本

前言

从希尔开始,排序的速度就开始上升了,这里的排序开始上一个难度了,当然难一点的排序其实也不是很难,当你对于插入排序了解的足够深入的时候,你会发现其实希尔就是插入的异形,但是本质上还是一样的

希尔排序gif

希尔排序单趟实现

1,希尔排序本质就是插入排序的进化,插入排序是寻找比较进行插入,希尔这个人觉得插入排序有点慢,就觉得我们可不可以进行预排序,也就是数值原来是0-9的情况下,最坏的情况我们需要循环9次数才能找到需要插入的点在哪,那么此时我们能不能进行一个预排序

2,所谓的预排序就是,我们假设几个为一组,几个为一组,这个组的变量我们设置为gap。假设处置3个为一组,那么gap=3

3,此时我们可以把这一组,先采取插入排序的方式进行预排序,预排序之后我们就会发现这一组的这条线上的数值已经有序

4,多趟实现只是反复的实现第一趟的实现的逻辑

希尔排序的多趟实现

1,多趟实现只是反复的实现第一趟的实现的逻辑

2,我们需要先知道单趟遍历的时候,我们需要假设gap一组的,这个中间的元素是没有的,那么此时此时一组就是两个数值,我们需要让这两个数值进行交换

3,这两个数值交换之后我们这个时候需要循环开始插入排序的逻辑,也就是假设前面的两个数值是已经有序的,那么新插入的一个数值是需要排序的,我们进行排序

4,一趟结束之后,我们继续多趟实现,这几个数值继续预排序

5,继续预排序

6,此时gap=3,那么我们继续,gap/2=1,之后继续进行预排序,此时我们就得到了这个排序正确的数值

希尔排序代码的实现-版本1

//希尔排序
void ShellSort(int* a, int n)
{
	int gap = n - 1;
	//定义gap,这里循环停止的条件是>1,原因是+1了,已经恒大于0了,所以需要大于1,等于都不可以
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		//循环实现每一组
		for (int j = 0; j < gap; j++)
		{
			//gap单趟实现
			for (int i = j; i < n - gap; i += gap)
			{
				int end = i; int tmp = a[end + gap];
				//一组的实现
				while (end >= 0)
				{
					if (tmp < a[end])
					{
						a[end + gap] = a[end];
						end -= gap;
					}
					else
					{
						break;
					}
				}
				//交换找到的数值
				a[end + gap] = tmp;
			}
		}
	}
}

 解释:

  1. 函数ShellSort接受两个参数:一个指向整数数组a的指针和数组的长度n

  2. 初始化间隔gap为数组长度n - 1,这是希尔排序开始时的最大间隔。

  3. while循环用于逐步减小间隔,直到间隔为1。当gap大于1时,循环继续。

  4. 在每次while循环的开始,重新计算间隔gap。这里使用的是gap = gap / 3 + 1,这是一种常见的间隔序列,由Donald Shell提出。

  5. 外层for循环用于遍历数组,步长为当前的间隔gap

  6. 内层for循环用于实现插入排序,但仅限于间隔gap内的范围。

  7. 在内层循环中,end变量记录当前考虑的元素的索引,tmp变量暂存当前要插入的元素。

  8. while循环用于在间隔gap内从后向前扫描,找到tmp应该插入的位置。

  9. 如果tmp小于当前比较的元素a[end],则将a[end]向后移动一个间隔gap的距离,为tmp腾出空间。

  10. 如果tmp大于或等于a[end],则while循环结束,找到了tmp应该插入的位置。

  11. 循环结束后,将tmp赋值给a[end + gap],完成插入操作。

  12. 这个过程重复进行,直到数组中的所有元素都被扫描并插入到正确的位置。

代码逻辑:

  • 希尔排序通过多个插入排序的变体来工作,每个变体都有一个特定的间隔。
  • 初始时,间隔较大,排序的稳定性较差,但可以快速减少无序度。
  • 随着间隔逐渐减小,排序的稳定性逐渐提高,最终当间隔为1时,算法变为普通的插入排序,确保数组完全有序。

注意:

  • 希尔排序不是稳定的排序算法,因为它可能会改变相等元素的相对顺序。
  • 希尔排序的时间复杂度通常在 𝑂(𝑛log⁡𝑛) 和 𝑂(𝑛^2) 之间,具体取决于间隔序列的选择。
  • 希尔排序的空间复杂度是 𝑂(1,因为它是原地排序算法,不需要额外的存储空间。

希尔排序代码的实现-版本2

上面那个代码一般是教学使用,书写会更加详细理解,但是很多书本会这样写

这里的关键在于,不再进行先一组排序结束,再反过来进行下一组反复执行

而是直接这一组实现完毕之后,++,直接进行下一组的实现,本质上还是一样的

只是直接这样书写,容易不理解

//希尔排序
void ShellSort02(int* a, int n)
{
	int gap = n - 1;
	//定义gap,这里循环停止的条件是>1,原因是+1了,已经恒大于0了,所以需要大于1,等于都不可以
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		//循环实现每一组+//gap单趟实现
		for (int i = 0; i < n - gap; i++)
		{
			int end = i; int tmp = a[end + gap];
			//一组的实现
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			//交换找到的数值
			a[end + gap] = tmp;
		}
	}
}

解释:

  1. 函数ShellSort02接受两个参数:一个指向整数数组a的指针和数组的长度n

  2. 初始化间隔gap为数组的最后一个索引n - 1

  3. while循环用于逐步减小间隔,直到间隔小于或等于1。循环的条件是gap > 1,这是因为间隔在每次迭代中都会减小,所以不需要检查gap == 1的情况。

  4. while循环内部,重新计算间隔gap。这里使用的计算方法是gap = gap / 3 + 1,这是一种常见的间隔序列,旨在逐步减小间隔,直到达到1。

  5. 外层for循环遍历数组,直到i < n - gap,即遍历到数组的末尾减去当前间隔的位置。

  6. 在外层for循环中,end变量记录当前考虑的元素的索引,tmp变量暂存当前间隔位置的元素值。

  7. 内层while循环用于在数组中找到tmp应该插入的位置。它从当前索引end开始,向前以间隔gap的距离进行比较。

  8. 如果tmp小于当前比较的元素a[end],则将a[end]向后移动一个间隔gap的距离,为tmp腾出空间。

  9. 如果tmp大于或等于a[end],则while循环结束,找到了tmp应该插入的位置。

  10. 循环结束后,将tmp赋值给a[end + gap],完成插入操作。

  11. 这个过程重复进行,直到数组中的所有元素都被扫描并插入到正确的位置。

代码逻辑:

  • 希尔排序通过多个插入排序的变体来工作,每个变体都有一个特定的间隔。
  • 初始时,间隔较大,随着算法的进行,间隔逐渐减小,直到变为1,此时算法变为普通的插入排序。
  • 通过逐步减小间隔,希尔排序能够在每次迭代中对数组的更大范围内的元素进行排序,从而减少比较和移动的次数。

希尔排序gap的界定

一般来说,一组为多少这个不好说,希尔开始书写的时候,gap是/2,来进行书写的,但是被认为效率最高的是,除以3+1,但是/3+1有一个弊端就是这个是恒大于0的,所以终止条件应该换为大于1就继续循环,小于等于1就停止循环

希尔排序的时间复杂度

希尔排序的时间复杂度取决于所选择的间隔序列,它通常介于以下范围:

  1. 最好情况:对于某些特定的间隔序列,希尔排序可以达到O(nlogn) 的时间复杂度,这与快速排序或归并排序相当。

  2. 平均情况:平均情况下,希尔排序的时间复杂度通常被认为是 O(n(logn)2),这比=O(nlogn) 稍差,但仍然比普通插入排序的 𝑂(𝑛^2) 好得多。

  3. 最坏情况:最坏情况下,希尔排序的时间复杂度可以退化到𝑂(𝑛^2),这通常发生在间隔序列选择不佳时。

  4. 实际性能:在实际应用中,希尔排序的性能通常比普通插入排序好,但不如快速排序、堆排序或归并排序。它的实际性能还取决于数据的初始状态和间隔序列的选择。

  5. 间隔序列的影响:不同的间隔序列对希尔排序的性能有很大影响。例如,使用Hibbard 间隔序列或Sedgewick间隔序列可以提高性能,有时甚至可以达到接近 O(nlogn) 的效率。

  6. 空间复杂度:希尔排序是原地排序算法,其空间复杂度为 𝑂(1)。

  7. 稳定性:希尔排序不是稳定的排序算法,这意味着相等的元素在排序后可能会改变它们原来的顺序。

总的来说,希尔排序是一种有效的排序算法,特别是对于中等大小的数据集或者当数据已经部分有序时。然而,对于大型数据集,通常推荐使用其他更高效的排序算法,如快速排序、堆排序或归并排序。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解决linux下载github项目下载不下来,下载失败, 连接失败的问题

第一步&#xff1a;打开/etc/hosts文件 linux vim /etc/hosts 第二步&#xff1a;文件拉到最下面&#xff0c;输入以下内容 linux #GitHub Start 140.82.113.3 github.com 140.82.114.20 gist.github.com 151.101.184.133 assets-cdn.github.com 151.101.184.133 raw.githubus…

在有限的分数有限下如何抉择?是选好专业还是选好学校

随着2024年高考的落幕&#xff0c;无数考生和家长站在了人生的重要十字路口。面对成绩单上的数字&#xff0c;一个难题摆在了面前&#xff1a;在分数限制下我们该如何平衡“心仪的专业”与“知名度更高的学校”之间的选择&#xff1f; 一、专业决定未来职业走向 选择一个好的专…

PostgreSQL源码分析——initdb

数据库初始化 在安装完数据库后&#xff0c;需要进行初始化数据库操作&#xff0c;对应PostgreSQL数据库中就是需要进行initdb后&#xff0c;才能对数据库进行启动。initdb的过程&#xff0c;其实就是创建数据库实例的过程&#xff0c;生成模板数据库和相应的目录、文件信息&a…

vue大作业-端午节主题网站

vue大作业-端午节主题网站介绍 端午节&#xff0c;又称为龙舟节&#xff0c;是中国的传统节日之一&#xff0c;每年农历五月初五庆祝。这个节日不仅是纪念古代爱国诗人屈原的日子&#xff0c;也是家人团聚、共享美食的时刻。今天&#xff0c;我们非常高兴地分享一个以端午节为…

如何完美解决 Oracle Database 19c 安装程序 - 第7步(共8步)卡住,半小时都不动

&#x1f680; 如何完美解决 Oracle Database 19c 安装程序 - 第7步&#xff08;共8步&#xff09;卡住&#xff0c;半小时都不动 摘要 在安装 Oracle Database 19c 时&#xff0c;很多用户会在第7步&#xff08;共8步&#xff09;遇到卡住的问题&#xff0c;尤其是安装程序长…

【html】用html5+css3+JavaScript制作一个计数器

目录 简介&#xff1a; 效果图&#xff1a; 源码&#xff1a; html: CSS: JS: 源码解析&#xff1a; 简介&#xff1a; 在日常生活当中很多事情都需要用到计数器特别是在体育运动当中&#xff0c;可以我们那么我们可不可以通过网页来制作一个计数器呢答案是肯定的我们需要利…

【Python】Redis数据库

Redis数据库 Unit01一、Redis1.1 概述1.2 安装1.3 Redis-cli1.4 数据类型1.5 字符处理1.6 键的命名规则 二、通用命令三、字符串(String)3.1 概述3.2 常用命令3.3 应用场景 四、列表(List)4.1 概述4.2 常用命令 五、集合(SET)5.1 概述5.3 常用命令 六、有序集合6.1 概述6.2 常用…

智慧养老,乐享晚年 — 探索新时代的养老模式

​随着科技的飞速发展和人口老龄化趋势的加剧&#xff0c;传统的养老模式已经无法满足现代社会的需求。人们期待在晚年能够享受到更加智能、便捷、舒适的生活。智慧养老&#xff0c;作为一种融合现代科技与养老服务的新型模式&#xff0c;正逐渐成为时代的选择&#xff0c;为老…

java第二十五课 —— 多态

多态 传统的方法带来的问题是什么?如何解决&#xff1f;问题是&#xff1a;代码的复用性不高&#xff0c;而且不利于代码维护。 未使用多态时候的例子&#xff1a; Poly01.java&#xff1a; package com.hspedu.poly_;public class Poly01 {public static void main(Strin…

【CT】LeetCode手撕—236. 二叉树的最近公共祖先

目录 题目1- 思路2- 实现⭐236. 二叉树的最近公共祖先——题解思路 3- ACM实现 题目 原题连接&#xff1a;236. 二叉树的最近公共祖先 1- 思路 模式识别 模式1&#xff1a;二叉树最近公共祖先 ——> 递归 判断 递归思路&#xff0c;分情况判断&#xff1a; 1.参数及返…

Linux系统OpenSSH_9.7p1升级详细步骤

版本说明 当前内核版本如下 当前操作系统版本如下 当前OpenSSH版本和OpenSSL版本如下 升级说明 openssh依赖于openssl和zlib&#xff0c;而openssl依赖于zlib&#xff0c;所以我们要先安装zlib&#xff0c;然后是openssl&#xff0c;最后是openssh。zlib-1.3.1下载地址&#…

Folly,一个强大的C++库

目录 1.引言 2.Folly库的特点 3.Folly库的应用场景 4.示例代码 5.总结 1.引言 Folly 是Facebook开发的一个开源、无许可&#xff08;Apache 2.0&#xff09;的现代C库&#xff0c;旨在提升性能和简化编写复杂任务的工作流程。它包含了一系列用于系统级编程的工具&#xff…

白蚁监测装置:支持北斗定位

TH-BY2白蚁监测控制管理系统原理 采用白蚁喜欢吃的食物做诱饵&#xff0c;吸引白蚁取食&#xff0c;取食过程中触动报警装置。报警装置发出信号&#xff0c;通过物联网传输到监控系统&#xff0c;经过数据处理&#xff0c;监测结果呈现给用户。用户通知白蚁防治专业人员&#x…

618数码好物有哪些?热门榜单强势出炉

大家好&#xff01;随着6.18购物狂欢节的来临&#xff0c;我可以明白在面对非常吸引人的商品时&#xff0c;“选择困难症”就上来了。因此&#xff0c;为了帮助大家在这场购物盛事中有方向&#xff0c;我特意结合个人使用体验和市场研究&#xff0c;为大家筛选了几件既具有超高…

CSP-J/S初赛01 计算机概述和计算机硬件系统

第1节 计算机概述 1.1 计算机的发展 代别 年代 逻辑&#xff08;电子&#xff09;元件 第一代 1946&#xff0d;1958 真空电子管 第二代 1959&#xff0d;1964 晶体管 第三代 1965&#xff0d;1970 集成电路 第四代 1971&#xff0d;至今 大规模、超大规模集成电…

Einops 张量操作快速入门

张量&#xff0c;即多维数组&#xff0c;是现代机器学习框架的支柱。操纵这些张量可能会变得冗长且难以阅读&#xff0c;尤其是在处理高维数据时。Einops 使用简洁的符号简化了这些操作。 Einops &#xff08;Einstein-Inspired Notation for operations&#xff09;&#xff…

HTTP 415错误状态码

HTTP 415错误状态码是指"Unsupported Media Type"&#xff08;不支持的媒体类型&#xff09;。这通常发生在客户端向服务器发送请求时&#xff0c;请求中包含的媒体类型&#xff08;例如Content-Type头部&#xff09;不被服务器支持或识别的情况下。 解决方法&#…

Erpnext安装

Erpnext安装 环境要求 Ubuntu 23.04 x86_64 Python 3.10.12 pip 23.0.1 node v18.16.0 npm 9.5.1 yarn 1.22.22 MariaDB 10.11.2 Redis 7.0.8 wkhtmltox 0.12.6.1 bench 5.22.6环境安装 Reids 安装 // 安装7.0.8 也可不指定版本 直接执行 sudo apt install redis-server s…

XX集团网上客户管理系统投标书技术部分(358页WORD)

方案介绍&#xff1a;针对客户不断增加的便民查询&#xff0c;业务受理等实际需求&#xff0c;我们将积极整合国内外人才、技术、产品资源&#xff0c;打造XX最便捷的网上处理平台。在平台建设和运营基础上&#xff0c;持续探索各种创新模式&#xff0c;发展多种有针对性的衍生…

攻防演练“轻装上阵” | 亚信安全信舱ForCloud 打造全栈防护新策略

网络世界攻防实战中&#xff0c;攻击风险已经从代码到云横跨全栈技术点&#xff0c;你准备好了吗 云服务器&#xff0c;攻击众矢之的 2022年超过38万个Kubernetes API服务器暴露公网&#xff0c;成为攻击者目标。云服务器&#xff0c;尤其是开源设施&#xff0c;一直以来不仅是…