排序算法--希尔排序

希尔排序(Shell Sort)是一种高效的排序算法,它是插入排序的一种改进版本(插入排序可以查看我的上一篇文章)。以下是关于希尔排序的详细讲解:

基本思想

希尔排序的基本思想是将原始数据集分割成若干个子序列,然后对每个子序列进行插入排序。这些子序列是由相隔一定“增量”的元素组成,随着算法的进行,这个增量会逐渐减小,直到为1。这样可以使得数据在预排序阶段变得部分有序,从而在最终的全局排序中提高效率。

算法步骤

  1. 选择间隔:想象你有一堆扑克牌,你想要让这些牌变得有序。希尔排序的第一步就像是从这堆牌中挑出一部分牌来先排序。这部分牌的选取基于一个“间隔”或者说是“步长”。,这个步长会设置为大一点的数字,比如牌堆长度的一半。

  2. 分组排序:根据选定的步长,把整堆牌分成几组。每一组中的牌都是隔了相同步长位置的。然后,就像玩接龙游戏一样,对每组中的牌按大小顺序排列好。

  3. 减小步长:当所有组都排好序后,减小步长(通常是1/3步长)。然后,用这个新的步长再次把牌分组,再次对每组进行排序。

  4. 重复排序:重复步骤2和3,每次都减小步长,直到步长变成1。当步长为1时,整个牌堆(也就是原始数组)中的所有牌都会被排序。

  5. 最终排序:最后一步,当步长为1,实际上就是执行了一次常规的插入排序。但这时候因为牌已经部分有序了,所以这次排序会很快。

示例代码(从小到大)

void ShellSort(int* a, int n)
{
	int gap = n;//gap为步长
	while (gap > 1)
	{
		gap = gap / 3 + 1; //+1可以保证最后一次一定为1
		for (int 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;
			}
		}
	}

}

时间复杂度

希尔排序的时间复杂度取决于所选择的增量序列。最佳情况下,时间复杂度可以达到O(n log n),而平均和最坏情况的时间复杂度通常介于 (O(n^1.3) ) 和 ( O(n^2) ) 之间。由于增量序列的选择对性能影响很大,因此没有固定的最坏时间复杂度。

空间复杂度

希尔排序的空间复杂度是 ( O(1) ),因为它只需要一个额外的存储空间来交换元素,不需要额外的数组或数据结构。

优点

  • 效率提升:相比于基本的插入排序,希尔排序的效率通常会更高,因为它在排序前先将数据预排序,使数据更加有序。
  • 简单实现:希尔排序的算法实现相对简单,只需要对直接插入排序稍作修改即可。

缺点

  • 稳定性:希尔排序是一种不稳定的排序算法,因为在排序过程中相等的元素可能会改变它们之间的相对顺序。
  • 增量选择:增量序列的选择对算法的性能影响很大,但并没有一种最优的增量序列可以适用于所有情况。
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值