插入排序-C语言版本

 前言

插入排序是很重要的排序,著名的希尔排序就是从插入排序演变过来的,所以我们需要并且很多时候有些面试也是会面试插入排序的,所以需要好好捋清楚插入排序的逻辑是什么

插入排序gif

插入排序单趟实现

1,插入排序我们需要假设最后一个数值也就是end+1是需要排序的,其他都是排序好的

2,把end+1这个下标的数值存放在tmp里面,并且和前面进行比较

3,如果遇见的元素比tmp大,我们继续往前移动进行比较,同时a[end]=a[end+1]往后覆盖

4,当遇见的是比tmp小的数值的时候,此时我们找到了tmp数值应该在的位置,进行插入

插入排序注意事项

这里需要注意的关键也是区间问题,假设数组有n个,那么end就是倒数第二个下标,end+1就是最后一个下标,是为了防止越界

我们需要小于n-1,因为,end=n-1;end+1=n,那么就越界了

所以在循环最大值里面,end=i=n-2,;end+1=n-1(最后一个数值)

插入排序代码的实现

//插入排序
void InsertionSort(int* a, int n)
{
	//多趟实现,这里n的截止条件-1,是因为下标从n-1就结束了,
	//不过我们需要小于n-1,因为,end=n-1;end+1=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];
				end--;
			}
			else//找到了,此时跳出循环就可以
			{
				break;
			}
		}
		//这里是很多人会搞混乱的一点,
		//因为是找到了,所以end还没有继续移动,但是end+1+1的元素已经移动,所以end+1的位置是tmp应该出现的位置
		a[end + 1] = tmp;
	}
}

解释:

  1. 函数InsertionSort接受两个参数:一个指向整数数组a的指针和数组的长度n

  2. 外层循环从索引0遍历到n-1。每次迭代,i代表已排序部分的最后一个元素的索引。

  3. 在外层循环的每次迭代中,end变量被设置为当前索引i,表示当前考虑的元素的索引。tmp变量存储了a[i + 1]的值,这是未排序的第一个元素,也是我们准备插入到已排序部分的元素。

  4. 内层while循环用于在已排序部分从后向前扫描,找到tmp应该插入的位置。end变量随着比较逐步递减。

  5. while循环中,如果tmp小于当前比较的元素a[end],则将a[end]向后移动一个位置,为tmp腾出空间。

  6. 如果tmp大于或等于a[end],则while循环通过break语句结束,找到了tmp应该插入的位置。

  7. 循环结束后,将tmp赋值给a[end + 1],完成插入操作。

  8. 这个过程重复进行,直到数组中的所有元素都被扫描并插入到正确的位置。

代码逻辑:

  • 插入排序的基本思想是,对于数组中的每个元素,将其插入到前面已经排好序的子数组中的正确位置。
  • 初始时,认为数组的第一个元素是已排序的。然后,从第二个元素开始,逐个插入到前面的已排序序列中。
  • 每次插入操作都需要将元素与已排序序列中的元素进行比较,直到找到合适的插入点。

注意:

  • 这段代码在插入元素时,如果插入点是数组的开始,那么不需要进行任何移动操作,直接插入即可。
  • 代码中的end变量用于记录当前比较的元素在数组中的位置,而tmp变量用于暂存当前要插入的元素。
  • 插入排序是稳定的排序算法,因为它不会改变相等元素的相对顺序。

性能:

  • 插入排序的平均时间复杂度和最坏时间复杂度都是 𝑂(𝑛^2),其中 n 是数组的长度。
  • 插入排序的空间复杂度是 𝑂(1),因为它是原地排序算法,不需要额外的存储空间。

插入排序的时间复杂度

插入排序算法的时间复杂度取决于数组的初始顺序,具体如下:

  1. 最佳情况:如果输入数组已经是完全有序的,插入排序只需要进行 n 次比较(每次比较后插入一个元素到已排序部分),而不需要进行任何交换。在这种情况下,时间复杂度是O(n)。

  2. 平均情况:在平均情况下,插入排序的时间复杂度是 O(n^2)。这是因为每个元素都需要与已排序部分的多个元素进行比较,平均下来,每个元素需要比较n/2次。

  3. 最坏情况:如果输入数组是完全逆序的,插入排序需要进行n(n−1)​/2次比较和 n(n−1)​/2次交换,时间复杂度是 O(n^2)。

  4. 空间复杂度:插入排序是原地排序算法,它只需要一个额外的存储空间来暂存当前比较的元素,因此空间复杂度是 O(1)。

  5. 稳定性:插入排序是稳定的排序算法,它保持了相等元素的原始顺序。

时间复杂度的详细分析:

  • 插入排序通过构建有序序列来工作,对于未排序的数据,在已排序的序列中从后向前扫描,找到相应位置并插入。
  • 在每次迭代中,算法将当前元素与已排序序列中的元素逐一比较,找到合适的插入点。
  • 对于每个元素,比较操作可能需要进行 i 次(其中 𝑖i 是当前元素在数组中的位置),从第一个元素到最后一个元素,所需比较的总次数是递增的。

时间复杂度的数学表达式是:

总比较次数=1+2+3+…+(𝑛−1)=𝑛(𝑛−1)/2总比较次数

这表明插入排序的时间复杂度是 Θ(𝑛^2),尽管在最坏情况下时间复杂度较高,插入排序对于小规模数据集或部分有序的数据集来说是非常高效的。

  • 35
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值