希尔排序与插入排序

文章详细介绍了插入排序的工作原理,通过打牌的例子来解释其过程,并分析了在最好和最坏情况下的时间复杂度。接着,文章讲解了希尔排序,一种改进的插入排序,通过间隔序列来减少比较次数,提高效率,其时间复杂度接近于n^(1.4)。希尔排序在处理接近有序的数据时表现出色,常用于其他高级排序算法的小区间排序优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 插入排序

插入排序就像是我们打牌时整理我们的牌面一样,第一张视为有序,然后不断拿后面的牌插入到排好的牌中,这样牌的有效区域会不断增加,待排序的牌会越来越少,我们也就完成了牌的插入排序

//插入排序
void ShellSort(int* a, int n)
{
	   for (int i = 0; i < n - 1; i++)
	  {
		 int end = i;//第一个数字视为已排完序
		 int tmp = a[end + 1];//下一个数字为待插入数据
		 while (end >= 0)
		{
		  if (tmp < a[end])
			{
				a[end + 1] = a[end];//a[end+1]已被保存在tmp中
				end -= 1;//插入数字与有序区间中的下一个数字相比
			}
		  else
			{
				break;//直到a[end]>=tmp
			}
		}
		 a[end + 1] = tmp;
     }  
}

二插入排序时间复杂度分析

   还是按算时间复杂度的一般情况,那假设总共有n个元素,插入元素从第二个元素到第n个元素,

最坏情况讨论,比如降序排升序,第二个元素要往前比较插入1次,第三个元素插入两次.....,第n个元素插入n-1次,等差数列的结果我们都知道肯定是个n^2,但是这并不意味着该排序是无用的,在数组接近有序的情况下,比如只有两三个数字无序,插入排序只需要O(n),这种情况下只有冒泡的效率能接近插入排序,冒泡虽然也是O(n),但差不多是个4n,比插入排序稍微慢一点,该特殊场景下归并,堆排序,快排都比不过,所以即使快排,归并,堆排序是O(nlogn),但不意味着其它排序就要退出历史舞台。还有就是在小区间下,插入比堆排,归并,快排要优秀的多,所以插入排序还应用于归并和快排的小区间排序,可以减少递归次数。

三 希尔排序

//希尔排序
void ShellSort(int* a, int n)
{

	int gap = n;
	while (gap > 1)
   {
		gap /= 2;//如果模三要加一,因为/3最后结果不一定为一,
那样就不会变成插入排序,会使得排序结果接近有序,但不是完全有序。
先分为两组,每组的个数不是均分的,会出现一组多一个,一组少一个的情况 

      for(int j=0;j<gap;j++)该层for循环是控制排序的组,j++表示去下一组进行排序
     {
        for (int i = j; i <n-gap; i+=gap)//该层for循环一次循环是一组内的比较排序
		{
			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;
		}
     }  
   }
}

四  希尔排序代码简化(但有些不便于理解)

  下面代码和上面的代码几乎是一样的,但区别在于少了外层的for循环,这层本来是控制到下一组去排序的,先如今简化为一层for循环,内层for循环也就是把i+=gap改为i++,由于待插入数据下标最大为n-1,下标小于n,则有效区间的边界end小于n-gap。

//希尔排序
void ShellSort(int* a, int n)
{

	int gap = n;
	while (gap > 1)
	{
		gap /= 2;//模三要加一,因为/3最后结果不一定为一
先分为两组,每组的个数不是均分的,会出现一组多一个,一组少一个的情况 

		for (int i = 0; i <n-gap; i++)//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;
		}
	}
}

希尔排序的复杂度超出本人的数学范围,不好解释,大家就记住是接近n^(1.4)就好了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小何只露尖尖角

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值