数据结构·插入排序(直接插入排序、希尔排序)

一、直接插入排序

1、 核心思想

插入排序通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入 ,如此重复,直至完成序列排序。

2、 算法分析

直接插入排序 动图

  1. 从序列第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素,设为待插入元素,在已经排序的元素序列中从后向前扫描,如果该元素(已排序)大于待插入元素,将该元素移到下一位置。
  3. 重复步骤2,直到找到已排序的元素小于或者等于待排序元素的位置,插入元素
  4. 重复2,3步骤,完成排序。

3、代码实现

void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (a[end] > tmp)
			{
				a[end + 1] = a[end];
				end--;
			}
			else break;
		}
		a[end + 1] = tmp;
	}
}

在这段代码中,最精髓也最难理解的便是a[end + 1] = tmp;a[end] > tmp为真时,可以参考冒泡排序的思想把大于tmp的数往后挪,一直挪到a[end] <= tmp时或者end < 0(end = -1)时,无论是哪种情况end + 1都可以表示一个合法的且适合于tmp的位置。

二、希尔排序(缩小增量法)

1、 核心思想

希尔排序是插入排序的一种,是对直接插入排序的优化。其特点在于分组排序。

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

2、 为什么会出现希尔排序

直接插入排序有缺陷,当数据接近逆序或逆序的时候,排的非常慢,效率很低

1 .提高效率:直接插入排序的时间复杂度在最坏的情况下是O(n^2),当数据量较大时,排序效率会非常低。希尔排序通过先对相隔一定距离的元素进行排序,可以使数组变得部分有序,从而减少后续排序的移动次数,提高排序效率。
2.减少比较和移动次数:通过选择合适的增量序列,希尔排序可以有效地减少元素之间的比较和移动次数,尤其是在处理大量数据时,这种优势更为明显。

3、算法分析

希尔排序 动图演示

希尔排序实例

首先gap取5,此时相隔距离为5的元素分到了一组(一共五组,每组两个元素),然后对每一组分别进行插入排序
gap折半为2,此时相隔距离为2的元素被分到了一组(一共两组,每组五个元素),然后对每一组分别进行插入排序
gap再次折半为1,此时所有元素被分到了一组,对它进行插入排序,至此插入排序完成

4、gap值的影响

当gap初始值较大时:

优点:较大的初始 gap 可以使数据更快地变得部分有序,减少后续较小 gap 排序时的移动次数。
缺点:如果 gap 过大,可能会导致子序列中的元素数量较少,排序效果不明
显,甚至可能导致某些元素没有被充分排序。

当gap初始值较小时:

优点:较小的初始 gap 可以更精细地调整元素的位置,使数据更接近最终的有序状态。
缺点:如果 gap 过小,排序过程可能会变得类似于直接插入排序,效率较低。

gap 序列选择是多样化的,不同的 gap 序列对排序性能有显著影响。其中线性递减序列(n / 2, n / 4, n / 8, …1)即每次 gap 减半到最终为1是实现相对简单,容易理解但性能通常不如一些专门设计的序列。

5、代码实现

void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 2;
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (a[end] > tmp)
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else break;
			}
			a[end + gap] = tmp;
		}
	}
}

在代码实现上,需要注意while (gap > 1)也可以为gap >= 1循环次数多一次(n),在数据量较大时效率会有细微的差别。

总结

直接插入排序和希尔排序都是基于插入排序的思想,但它们在处理大规模数据时的效率和适用性有所不同。

  • 对于已经部分有序或完全有序的数据,直接插入排序通常表现更好,希尔排序虽然在处理大规模数据时效率较高,但在完全有序的数据上并没有明显的优势。
  • 对于小规模数据,直接插入排序通常足够。而对于大规模数据,希尔排序通常更高效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值