首页 > 编程语言 >排序算法--希尔排序

排序算法--希尔排序

时间:2024-07-27 19:27:43浏览次数:11  
标签:end -- 复杂度 步长 gap 希尔 排序

希尔排序(Shell Sort)是一种高效的排序算法,它是插入排序的一种改进版本(插入排序可以查看我的上一篇文章)。以下是关于希尔排序的详细讲解:

基本思想

希尔排序的基本思想是将原始数据集分割成若干个子序列,然后对每个子序列进行插入排序。这些子序列是由相隔一定“增量”的元素组成,随着算法的进行,这个增量会逐渐减小,直到为1。这样可以使得数据在预排序阶段变得部分有序,从而在最终的全局排序中提高效率。

算法步骤

  1. 选择间隔:想象你有一堆扑克牌,你想要让这些牌变得有序。希尔排序的第一步就像是从这堆牌中挑出一部分牌来先排序。这部分牌的选取基于一个“间隔”或者说是“步长”。,这个步长会设置为大一点的数字,比如牌堆长度的一半。

  2. 分组排序:根据选定的步长,把整堆牌分成几组。每一组中的牌都是隔了相同步长位置的。然后,就像玩接龙游戏一样,对每组中的牌按大小顺序排列好。

  3. 减小步长:当所有组都排好序后,减小步长(通常是1/3步长)。然后,用这个新的步长再次把牌分组,再次对每组进行排序。

  4. 重复排序:重复步骤2和3,每次都减小步长,直到步长变成1。当步长为1时,整个牌堆(也就是原始数组)中的所有牌都会被排序。

  5. 最终排序:最后一步,当步长为1,实际上就是执行了一次常规的插入排序。但这时候因为牌已经部分有序了,所以这次排序会很快。

示例代码(从小到大)

void ShellSort(int* a, int n)
{
	int gap = n;//gap为步长
	while (gap > 1)
	{
		gap = gap / 3 + 1; //+1可以保证最后一次一定为1
		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;
			}
		}
	}

}

时间复杂度

希尔排序的时间复杂度取决于所选择的增量序列。最佳情况下,时间复杂度可以达到O(n log n),而平均和最坏情况的时间复杂度通常介于 (O(n^1.3) ) 和 ( O(n^2) ) 之间。由于增量序列的选择对性能影响很大,因此没有固定的最坏时间复杂度。

空间复杂度

希尔排序的空间复杂度是 ( O(1) ),因为它只需要一个额外的存储空间来交换元素,不需要额外的数组或数据结构。

优点

  • 效率提升:相比于基本的插入排序,希尔排序的效率通常会更高,因为它在排序前先将数据预排序,使数据更加有序。
  • 简单实现:希尔排序的算法实现相对简单,只需要对直接插入排序稍作修改即可。

缺点

  • 稳定性:希尔排序是一种不稳定的排序算法,因为在排序过程中相等的元素可能会改变它们之间的相对顺序。
  • 增量选择:增量序列的选择对算法的性能影响很大,但并没有一种最优的增量序列可以适用于所有情况。

标签:end,--,复杂度,步长,gap,希尔,排序
From: https://blog.csdn.net/SouTY_C/article/details/140459752

相关文章

  • C语言的函数递归
    一、递归的意义所谓函数递归,就是在某个函数中再次调用这个函数本身,做到函数自己调用自己,这个就是函数的递归。而函数的递归主要是的作用是将一个本身比较复杂,并且步骤繁多的函数逐次的递归使其变得简单化,就比如剥笋:我们想要得到里面能吃的部分,就需要剥笋。而笋的皮有很多层,每......
  • MathType7.4激活密钥免费获取?MathType7怎么输入激活码
    亲爱的数学爱好者们、科研工作者和教育工作者们,你们是否曾因为公式编辑而感到头大?今天我要来给大家种草一个神奇的软件——MathType,它不仅能够帮你轻松搞定各种复杂的数学公式编辑,还能让你的工作效率翻倍哦!MathType最新mac官方版本下载如下:https://wm.makeding.com/iclk/?zo......
  • C++ 虚拟加载程序
    哦!J B K!我来啦!!!目录代码效果总代码  新知识生化危机  结尾代码上代码!(上次是这样吗?)voidHideCursor()//影藏光标{ CONSOLE_CURSOR_INFOcursor_info={1,0}; SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);}还有!!! —————......
  • 【Go】基于 Go 1.19 的站点模板爬虫【实战演练版】
    0.前言Go语言,也被称为Golang,是由Google开发的一种开源编程语言,它在2009年首次发布,并在2012年正式开源。Go语言被设计用来简化大型软件的开发,特别注重并发编程和内存安全。0.1特点静态类型:Go是静态类型语言,这意味着类型在编译时已经确定,有助于在编译阶段捕捉错误......
  • tomat 启动项目请求中文乱码 日志乱码
    tomat启动项目请求中文乱码日志乱码tomat启动项目请求中文乱码日志乱码检查tomcat编码检查项目编码检查服务器编码修改catalina.bat测试tomat启动项目请求中文乱码日志乱码项目部署后请求信息中文乱码{""address":"娴嬭瘯","Province":"骞胯タ澹棌鑷......
  • Python 教程(二):语法与数据结构
    目录前言专栏列表语法特点实例代码基本数据类型变量命名规则赋值动态类型作用域示例代码运算符`list`、`set`和`dict`数据结构区别1.list(列表)2.set(集合)3.dict(字典)总结前言Python是一种计算机编程语言。每种编程语言都有自己的语法规则。在本教程中,我们将学......
  • 2024年大厂AI大模型面试题精编+答案解析!!
    前言随着AI市场,人工智能的爆火,在接下来的金九银十招聘高峰期,各大科技巨头和国有企业将会对AGI人才的争夺展开一场大战,为求职市场注入了新的活力。为了助力求职者在面试中展现最佳状态,深入理解行业巨头的选拔标准变得至关重要。尤其是对于AGI(ArtificialGeneralIntelligen......
  • c++11 新特性 超级详细
    目录C++auto类型推导完全攻略auto类型推导的语法和规则auto的限制auto的应用使用auto定义迭代器auto用于泛型编程C++decltype类型推导完全攻略decltype推导规则decltype的实际应用汇总auto和decltype的区别语法格式的区别对cv限定符的处理对引用的处......
  • C++输入输出流
    目录入门     C++cout.put():输出单个字符C++cout.write():输出字符串C++cout.tellp()和cout.seekp()方法详解 C++tellp()成员方法C++seekp()成员方法 C++cout格式化输出(超级详细)C++cout成员方法格式化输出使用流操纵算子格式化输出C++怎样对输入输出......
  • 【项目实战】解码软件工程:一文读懂DO/PO/BO/AO/DTO/DAO/POJO/VO的奥秘
    文章目录一文读懂DO/PO/BO/AO/DTO/DAO/POJO/VO的奥秘不同领域作用POJO(PlainOldJavaObject)VO(ValueObject)VO(ViewObject)的特点:实体类(Entity)数据传输对象(DTO)领域对象(DomainObject)持久化对象(PersistentObject)业务对象(BusinessObject)应用对象(ApplicationObject)......