一个初学者对希尔排序的理解

希尔排序

1)希尔排序(shell sort)这个排序方法又称为缩小增量排序,是1959年D·L·Shell提出来的。该方法的基本思想是:设待排序元素序列有n个元素,首先取一个整数increment(小于n)作为间隔将全部元素分为increment个子序列,所有距离为increment的元素放在同一个子序列中,在每一个子序列中分别实行直接插入排序。然后缩小间隔increment,重复上述子序列划分和排序工作。直到最后取increment=1,将所有元素放在同一个子序列中排序为止。
(2)由于开始时,increment的取值较大,每个子序列中的元素较少,排序速度较快,到排序后期increment取值逐渐变小,子序列中元素个数逐渐增多,但由于前面工作的基础,大多数元素已经基本有序,所以排序速度仍然很快。
(3)希尔排序步骤:
1、下面给出一个数据列:{2, 8 ,19 , 36 ,5,9}
2、第一趟取increment=n/3(关于increment的取法之后会有介绍)。将整个数据列划分为间隔为2的2个子序列,然后对每一个子序列执行直接插入排序,相当于对整个序列执行了部分排序调整。

在这里插入图片描述
排序后的结果如图
在这里插入图片描述

3、第2趟把间隔缩小(increment- -),当增量为1的时候,实际上就是把整个数列作为一个子序列进行插入排序
在这里插入图片描述
排序后就得到了结果
在这里插入图片描述
希尔排序c++代码如下

void shell_sort(int start , int end)//start是数组的起始下标=0 ; end是数组的末尾下标  = n-1
{
	int increment = (end - start + 1)/3;	//初始化划分增量  
	while (increment>0)//循环条件,如果increment=1排完序后跳出
	{

		for (int i = increment; i <= end; i++)//按照增量分组
		{
			if (numbers[i - increment] > numbers[i])//比较
			{
				int min = numbers[i];
				int j = i - increment;
				while (j >= start && numbers[j] > min)//与前面同组的数值比较
				{
					numbers[j + increment] = numbers[j];
					j -= increment;
				} 
				numbers[j + increment] = min;
				
			}
		}
		increment--;//增量递减
	}

}

注意:这里是一步步比较的(先一组的比较,在二组的比较循环),没有申请新的空间来存放不同的组的数据。

关于希尔排序的性能分析

1. 时间复杂度
希尔排序的复杂度和增量序列是相关的,增量序列就是上面举例中gap的序列(5,21),而增量序列也可以用其他算法,有的增量序列的复杂度至今还没有证明出来
{1,2,4,8,…}这种序列并不是很好的增量序列,使用这个增量序列的时间复杂度(最坏情形)是O(n^2)
Hibbard提出了另一个增量序列{1,3,7,…,2k-1},这种序列的时间复杂度(最坏情形)为O(n1.5)
Sedgewick提出了几种增量序列,其最坏情形运行时间为O(n^1.3),其中最好的一个序列是{1,5,19,41,109,…}
2. 空间复杂度为O(1)
3. 稳定性
虽然插入排序是稳定的,但是希尔排序不是稳定的,因为希尔排序在插入元素的时候是跳跃性插入,有可能破坏稳定性,如7 5 5 8,第一次分组之后,两个5在不同的两组中,第一组的5会和7交换使得两个5最终的前后顺序发生了改变

如果不太了解插入排序的可以点击看一下代码
以上为初学者个人的看法,如有问题欢迎指正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值