【八大排序】Shell排序

目录

前言

一、分组规则

二、代码实现

总结


前言

本文将介绍八大排序之一,Shell排序,Shell排序实际为直接插入排序的优化,使其时间复杂度降低。

“shell排序,又名希尔排序,被称作缩小增量排序,是1959年首次提出的。主要思想:假设待排序原素序列涵盖n个原素,取一个整数increment(小于n)作间隔,把所有的元素分为increment个子序列,全部距离是increment的元素,放在同一个子序列中,在每一个子序列中分别实施直接插入排序”,Shell排序的执行时间依赖于增量序列。

上次了解的插入排序,我们会发现一个特点,那就是如果数据序列越有序,我们调用直接插入排序时数据移动的次数就会减少。

由此科学家希尔提出这种算法,使排序的时间复杂度降于O( n ^ 2 ) 之下。

方法就是将原来的数据组分为多组,先进行局部的直接插入排序,达到数据的基本有序,再最后进行整体的排序,使数据真正有序。

希尔排序: 直接插入排序的优化

稳定性:  不稳定

时间复杂度O(n^1.3~1.5)(和增量数组取值有关)  

空间复杂度O(1)    


一、分组规则

我们先给出一组数:18  21  8  9  10  7  6  5  91  3  66  77  35  22  29

如果我们按照以上方式简单的进行分组,各组进行简单的排序过后,我们发现好像并没有什么明显的变化,距离我们想要的有序还差的较远,所以这是一种错误的分组。

因此,我们需要采取跳跃分割的策略:将相距某个“增量”的数据组成一个子序列,这样才能保证整体数据的相对有序,而不是局部有序。

注意,这里最后的增量大小必须为1,否则数据未达到完全排序。

在这里我们分别依照5,3,1的增量间隔进行分割:

到这里是不是发现在整体上出现了前面数据值较小,后面数据值较大的变化。

当我们进行最后一次整体排序后,达到以下的结果

并且因为分组后数据跳跃移动的缘故,对数据的移动次数大大减少,降低了时间复杂度。

二、代码实现

此处代码实现与直接插入排序大致相同

void Shell(int* ar, int n, int gap)
{
    ///此处与直接插入排序大致相同,仅仅增量部分存在差异
	for (int i = gap; i < n; i++)
	{
		int num = ar[i];
		int j = i - gap;
		for (j; j >= 0; j -= gap)
		{
			if (ar[j] > num)
			{
				ar[j + gap] = ar[j];
			}
			else
			{
				break;
			}
		}
		ar[j + gap] = num;
	}
}
void Shell_Sort(int* ar, int n)
{
    ///提供增量数组
	int gap[] = { 5,3,1 };
	int length = sizeof(gap) / sizeof(gap[0]);
	for (int i = 0; i < length; i++)
	{
		Shell(ar, n, gap[i]);
	}
}

总结

以上就是今天要学习的内容,本文介绍了Shell排序的排序过程和代码实现,Shell排序的时间复杂度在O( n ^ 2 ) 之下,是较为快速的几种算法之一,其在增量的思想需要进行认真思考和学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值