【排序】希尔排序

在这里插入图片描述
本篇博客由 CSDN@先搞面包再谈爱 原创,转载请标注清楚,请勿抄袭。

前言

个人觉得排序这东西应该先看一下图解,然后再听理论才能更容易入门。

所以我先给出图解:

图解

在这里插入图片描述
本人在网上找不到好的动图,这个看起来好像比较老,但是我觉得这张跟别的比更能体现出希尔排序的思想。

基本步骤

首先,希尔排序是基于插入排序的一个时间复杂度为O(N*logN)的一个很牛的排序。

怎么做呢?

大家应该能注意到,图解中每一趟排序的时候有的数背景颜色是一样的,像这样背景颜色相同的数为一组,我们一共可以分gap组。

那么什么是gap呢,就是当你选出一个数后,这个数后面所有的每加gap个位置的数定为一组数,看下图解:
在这里插入图片描述
这里的9 6 4 1为一组数,那么相应的剩下的数也可分组:
在这里插入图片描述
剩余的8 5 3是一组,7 5 2是一组。可以看到就是gap组数。

然后我们对每一组的数进行插入排序,就能使得每组的数都是有序的:
如果对插入排序不是很了解的话,请看我的上一篇博客:看插入排序就行
在这里插入图片描述

然后再把这些数弄回到数组中得到新的数组:
在这里插入图片描述
之后将gap减小,假如说现在gap减为2,继续分组:
在这里插入图片描述

对每一组的数进行插入排序:
在这里插入图片描述
然后再把这些数弄回到数组中得到新的数组:
在这里插入图片描述
可以看到跟前面没有变化,但是重点不是这,当我们把gap减为1时:
在这里插入图片描述
可以看到这组数已经非常接近有序了,这个时候我们再用插入排序的话,效率会大大提升(如果不知道为什么也请看我上一篇博客)。

整体思路

先选定gap,假设数据个数为n个。
一般情况下:

gap的初始值为n(看代码的时候就懂了)

gap每次变化的值为gap = gap / 2 或 gap = gap / 3 + 1(保证gap一定出现==1的情况)

然后每次分出gap组,对每一组的数进行插入排序。

直到当gap == 1的时候就是直接插入排序。

代码实现

//希尔排序
void ShellSort(int* a, int n)
{	
	int gap = n;//保证能够进入循环
	//如果此处gap为n/3+1或n/2的话就不能保证能进入循环
	//比如说n为2的时候
	while (gap > 1)
	{
		gap = gap / 3 + 1;//此处也可改为gap /= 2;
		for (int j = 0; j < gap; j++)
		{
			for (int i = j; i < n - gap; i += gap)
			{	//外面的这两层i,j循环也可以改为一层的,就是下面这个
				//for(int i = 0; i < n - gap; i++)//下面的这个完全是插入排序的方法了,基本是一模一样,就是把插入排序里面的1改为了gap
				int end = i;
				int key = a[end + gap];
				//单趟排序
				while (end >= 0)
				{
					if (a[end] > key)
						a[end + gap] = a[end];
					else
						break;

					end -= gap;
				}

				a[end + gap] = key;
			}
		}
	}
}

时间复杂度

希尔排序的时间复杂度的计算非常复杂,本人也不会,但是记住结论就行。

大概在O(N^1.3)这个量级,不过也可以记成O(N * logN)。

稳定性

不稳定

到此结束。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

先搞面包再谈爱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值