【C/C++】希尔排序(详细注释)

希尔排序的思想

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。

希尔排序的特性

1. 希尔排序是对直接插入排序的优化。
2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些书中给出的
希尔排序的时间复杂度都不固定:因为我们的gap是按照Knuth提出的方式取值的,而且Knuth进行了大量的试验统计,我们暂时就按照:O(N^1.25)到O(1.6*N^1.25) 来算。
4. 稳定性:不稳定

希尔排序的实现

希尔排序实际就是优化的插入排序,可以看到中间的代码跟插入排序的代码相似度是极高的,也就只是改了几个数。

void SelectSort(int* a, int n) // a指针为需要进行排序的数组的指针,n为需要排序的数组的数据个数
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1; // 减小每次预排序的组距,直到gap为1,gap为1则是正常的插入排序
		for (int i = 0; i < n - gap; ++i) // 把每个数都和前面的序列进行比较、插入,这里i不能到达n-gap是为了防止越界
		{
			int end = i;
			int tmp = a[end + gap]; // 备份本次循环准备要进行插入的值
			while (end >= 0)
			{
				if (a[end] > tmp) // 让即将进行插入的值与前面的序列以此进行比较
				{
					a[end + gap] = a[end]; // 如果该位置的值大于tmp则把该位置的值往后移动
					end -= gap;
				}
				else // 如果没满足上面if中的条件则代表找到了要进行插入的位置
				{
					break; // 结束循环准备进行值的插入
				}
			}
			a[end + gap] = tmp; // 把值进行插入
		}
	}
}

注意这里for循环中的i是每次增加1,虽然i是依次往后走的,但是每次进行排序的都是被划分到不同组的数据。也就是说不是按排完一组再拍一组的方式来预排序,而是每组各排一点每组各排一点地进行预排序。如果想要按一组排完再到下一组的话也是可以的,代码实现上会有细微的差别,但是算法的效率不会因此而改变。
在这里插入图片描述
假设初始数组为上面的样子,gap假设初始为5每次gap除以4,排序的过程就像上面这样所示

希尔排序的稳定性

虽然希尔排序是插入排序的优化,并且代码大部分也跟插入排序相同,但是希尔排序却是不稳定的。
希尔排序的这种分组是有可能把数组内相同值划分到不同的组内的,从而导致他们的相对位置发生改变,所以希尔排序是不稳定的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值