【插入排序】手撕八大排序之直接插入排序和希尔排序

目录

前言:

一.插入排序

1.直接插入排序

2.希尔排序 


前言:

排序一共有八种:冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序和计数排序这八种排序算法。

排序在我们现实生活中其实是非常常见的,而且很多地方的分不开它们,当我们在某软件网购的时候,我们可以使用价格排序,销量排序,好评排序来筛选我们想要的商品。

这里我选择销量和价格两个条件,软件就会自动的给顾客排好序,这底层的逻辑就是使用的排序算法,可知排序算法是非常重要的,只不过现在学习的八大排序是很基础的,后面的红黑树和AV树才是真正的巨头,现在的我们必须要打牢基础,脚踏实地的学习。 

一.插入排序

1.直接插入排序

插入排序顾名思义,就是一个一个的插入,如同我们摸扑克牌一样,当摸第一张牌上来的时候,直接放到手里面即可,摸第二张的时候,就和手里面的比较,看是放在后面还是前面。依次类推,每次摸牌起来的时候,手里的牌都是有序的,只需要把这张牌插入到有序的牌中即可。

注意:这里我们的排序都是排的升序。 

//直接插入排序
void InsertSort(int* a, int n)
{
	for (int i = 1; i < n; i++)
	{
		int end = i - 1;//这是有序数组的最后一个元素
		int temp = a[i];
		while (end >= 0)
		{
			if (temp < a[end])//待插入的数和最后这个数进行比较
			{
				a[end+1]=a[end];
				end--;//交换了,end就往前移一位,再继续进行比较
			}
			else
			{
				break;
			}
		}
		a[end + 1] = temp;
	}
}

这里动图不太理解,我们还是一样画图来理解。
第一次:
第二次: 

第三次: 

这时已经退出while循环了,但是数组中还有一位是空缺的,并且end已经不指向数组的位置了,所以最后一句的a[end+1]=temp,就是为了把这个位置给填上。 
就这样不断简单的重复,就可以把这个无序的数组排序为一个升序的数组。

直接插入排序的特性总结:
1. 元素集合越接近有序,直接插入排序算法的时间效率越高
2. 时间复杂度: O(N^2)
3. 空间复杂度: O(1) ,它是一种稳定的排序算法
4. 稳定性:稳定

2.希尔排序 

希尔排序是由美国计算机科学家 Donald Shell 在1959年提出的。当时,他发表了一篇名为 “A High-Speed Sorting Procedure” 的论文,介绍了这种排序算法。

希尔排序本质上是插入排序的一种改进版本。传统的插入排序在排序一个逆序的序列时效率较低,因为它每次只能将一个元素移动一个位置。为了解决这个问题,Shell 提出了一种逐步缩小增量的方法,即先比较距离较远的元素,然后逐渐缩小间隔,最终达到相邻元素之间的比较。
希尔排序的核心概念是使用一个增量序列,将待排序的序列分割成多个子序列,对每个子序列进行插入排序。然后逐渐缩小增量,直至增量为1,进行最后一次插入排序。通过这种方式,希尔排序能够高效地排序序列。

最后增量为1时,也就变成了直接插入排序了。 

动画演示:

第一次设置间隔为5,那么49和13比较然后进行排序,38和27进行比较然后进行排序。依次类推,直到把所有间隔为5的数先排序完。
第二次就把间隔缩小,继续排序,直到间隔为1了之后,再次排序就成立直接插入排序,这样排序了之后还数组的数据就变成有序的了。
但是这里有一个点需要我们注意,那就是如何将间隔逐渐缩小,到最后为1,这就需要对数组的大小做文章了。

//希尔排序
void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)//gap等于1,那么就排序完毕了,即退出循环
	{
		gap = gap / 3 + 1;
		//不管n是偶数还是奇数,只要最后+1,最后的gap一定会变成1
		for (int i = 0; i < n - gap; i += gap)
		//注意这里i要小于n-gap,不然下面的temp可能就会越界
		{
			int end = i;
			int temp = a[i + gap];
			while (end >= 0)
			//注意下面的逻辑和直接插入排序的逻辑是一样的,只是间隔不一样罢了
			{
				if (temp < a[end])
				{
					Swap(&a[end + gap], &a[end]);
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = temp;
		}
	}
}

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

 

  • 36
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 28
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值