当前位置: 首页 > article >正文

数据结构与算法:希尔排序

一、概念及其介绍

希尔排序是插入排序的一种,它是针对直接插入排序算法的改进。

希尔排序又称缩小增量排序,它通过比较相距一定间隔的元素来进行,各趟比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止。

希尔排序的基本思想是将待排序的元素分成多个子序列,每个子序列通过插入排序进行排序。初始时,整个序列被分成多个子序列,每个子序列包含相隔一定增量的元素。随着增量的逐渐减小,子序列的元素逐渐合并,最终当增量减至1时,整个序列完成排序。

希尔排序的时间复杂度是O(N^{1.3-2}),空间复杂度为常数阶O(1)

首先,把n个数分成gap组进行预排序

int gap = 3;
for (size_t i = 0; 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;
}

end的位置要小于n - gap,如果大于,会越界。这种方法是一组一组的走完,先走完红色的,让它成为有序,然后再走绿色的,最后走蓝色的。但是这样总体上还不是有序的,所以,最后还要走一次插入排序。

那有没有直接完成排序的方法呢?还有就是gap为什么是3,可以是其他数字吗?

我们首先要知道

gap越大,可以越快跳到后面,小的数就可以越快跳到前面,但越不接近有序。

gap越小,跳的越慢,但是越接近有序。当gap == 1时,相当于插入排序,其结果就有序了。

所以我们接下来代码要改进了

void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		for (int j = 0; j < gap; j++)
		{
			for (size_t 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;
			}
		}
	}
}

gap = gap / 3 + 1,不管gap为什么值,都可以保证gap最后都为1,当gap==1时相当于一次直接插入排序,结果为有序。当然也可以不除3,可以除其他值,但是要保证gap最后为1.

外层for循环完成gap组依次排序,内层for循环完成每组的排序。一组完成排序再接着下一组进行排序。

还有一种并着走的写法,但是从效率上来说没有改变。

void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		for (size_t 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;
		}
	}
}


http://www.kler.cn/a/574569.html

相关文章:

  • HTML 编辑器推荐与 VS Code 使用教程
  • springcloud智慧工地物联网云管理系统源码
  • LeetCode 双指针章节
  • 最新的前端场景面试题
  • 无显示器安装访问树莓派3B+
  • 【C#】async与await介绍
  • vue实现日历签到效果
  • C# foreach中获取循环索引的4种方式
  • 【机械视觉】C#+visionPro联合编程———【一、C# + VisionPro 联合编程详解以及如何将visionPro工具加载到winform】
  • unity调用本地部署deepseek全流程
  • 函数扩展【ES6】
  • Manus AI 全球首款通用型 Agent,中国制造
  • 极狐GitLab 17.9 正式发布,40+ DevSecOps 重点功能解读【一】
  • MATLAB中startsWith函数用法
  • 面试基础---Redis 延迟队列深度解析
  • ssm_mysql_暖心家装平台
  • 华为OD机试-Excel单元格数值统计(Java 2024 E卷 200分)
  • Mybatis中的分页操作,如何使用PageHelper进行分页,以及Spring Boot整合Mybatis Plus分页
  • SpringBoot读取类路径下文件
  • 【DeepSeek】5分钟快速实现本地化部署教程