【排序】插入排序

插入排序

简介:

插入排序如同我们日常的时候玩的扑克牌,我们习惯从从小到大排列。假设扑克牌的从小到大的顺序是 1…K 一共13张,此时你手里的牌[1,3,7,9] ,现在又抽了一张4,你得按从小到大的顺序插入其中,那么如何插入呢?我们就必须两张牌之间进行逐一比较,插入到符合的位置。这就是插入排序。

算法思想:

我们没一次都将下标为end+1的位置的数向前插入,插入到[0,end]中。而且每一次插入都是将end + 1插入到[0,end ]有序区间中的

每一次单趟排序的过程:
数组 v【1,5,3,7,9】按从小大的顺序进行排序

  1. end = 0时, end + 1 = 1。将end +1位置的数插入到[0,0]中,发现 5比1大,就不用插入 数组[1,5](0到end+1此时为升序)
  2. end = 1时, end + 1 = 2。将end + 1位置(3)插入到 [0,1]中,发现3比5小,向前插入 最后得到数组[1,3,5] (0到end+1此时为升序)
  3. end = 2时, end + 1 = 3。已经是升序,不进行向前插入 [1,3,5,7]
  4. end = 3时,end + 1 = 4。 已经是升序,不进行向前插入 [1,3,5,7,9]

值得注意的是:因为插入的过程是从前往后进行插入的,end + 1是当前要向前插入的值的下标,所以我们的 end+1也是向后遍历的。
所以end + 1要从1遍历到数组最后一个元素对应的下标(n-1)。 所以end的范围就是 [0,n-2] 闭区间

代码实现:
void InsertSort(int* arr, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
		int tmp = arr[end + 1]; // 要插入的元素,先将它保存起来 
		while (end >= 0)        // 向前找适合插入的位置
		{
			if (tmp < arr[end]) // 如果tmp < arr[end],就是这个位置可以进行插入
			{
				arr[end + 1] = arr[end]; //,则需要将arr[end]向后移动,覆盖后面的数,此时arr[end+1]已经保存在tmp当中
			}
			else
			{
				break;
			}
			end--;

			arr[end + 1] = tmp; //将存放arr[end+1]的临时变量tmp赋给arr[end]
		}
	}
}
void PrintArray(int*arr, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", arr[i]);
	}

	printf("\n");
}
int main()
{
	int  arr[] = { 1, 3, 4, 9, 3, 5, 7, 0 };
	InsertSort(arr, sizeof(arr) / sizeof(int));
	PrintArray(arr, sizeof(arr) / sizeof(int));
	system("pause");
}

运行结果:
在这里插入图片描述

时间复杂度分析 O(N^2)

因为一个for循环遍历,每一次都要找到要插入的元素。每个插入的元素还要进行一次循环,向前找插入的位置。所以两个循环的长度都是数组长度的级别。所以是O(N^2)。
但是最好的情况下:顺序的情况,就不用去为每一个元素找插入的位置。只用一个for循环从头遍历到尾结束
最坏的情况下:加入我们要排顺序,结果数组逆序。则每一次找插入的位置的时候,都要把之前排好序的数组在遍历一遍。所以是O(N^2)。我们通常将最坏情况下的时间复杂度称为算法的时间复杂度

空间复杂度分析 O(1)

因为没有用额外的空间,在常数的空间下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值