【数据结构】直接插入排序

在这里插入图片描述

👦个人主页:Weraphael
✍🏻作者简介:目前正在学习c++和算法
✈️专栏:数据结构
🐋 希望大家多多支持,咱一起进步!😁
如果文章有啥瑕疵
希望大佬指点一二
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注😍


一、基本思想

在这里插入图片描述

基本思想:把待排序的元素从小到(从大到小)逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列

实际中,玩扑克牌时,整理一副牌从小到大或者从大到小就用到了插入排序的思想

在这里插入图片描述

二、算法原理

  1. 首先序列中的第一个元素(下标为0)是不需要排序的。因为当插入第一个元素时,序列中也没有元素与其比较,因此默认为有序。
  2. 当插入第ii ≥ 1)个元素时,由于要挪动数据,我们拿待插入元素当前数组内的最后一个元素(下标end)进行比较,若a[i] < 数组最后一个元素,则将当前元素向后移动一个单位,并将end--继续向前比较,直到找到合适位置为止。

这里为大家举几个样例

  • 插入1

在这里插入图片描述

  • 插入3

在这里插入图片描述

  • 插入5

在这里插入图片描述

三、代码实现

以下代码以升序为例:

#include <stdio.h>

// n - 元素个数
void InsertSort(int* a, int n)
{
	// 数组第一个元素不需要参与排序
	// 下标从1开始
	for (int i = 1; i < n; i++)
	{
		// end - 每一次数组最后一个元素的下标
		// InsertNum - 要插入的元素
		int end = i - 1; 
		int InsertNum = a[i];
		
		while (end >= 0)
		{
			// 如果插入的元素比当前元素小,就要往后挪动数据
			if (a[end] > InsertNum)
			{
				a[end + 1] = a[end];
				end--;
			}
			// 插入比当前元素大,则直接插入
			else
			{
				a[end + 1] = InsertNum;
				break;
			}
		}
		//当循环结束后,可能存在头插
		if (end == -1)
		{
			a[end + 1] = InsertNum;
	    }
	}
}

当然以上代码在插入过程中有重复代码,因此可以整合

#include <stdio.h>

// n - 元素个数
void InsertSort(int* a, int n)
{
	// 数组第一个元素不需要参与排序
	// 下标从1开始
	for (int i = 1; i < n; i++)
	{
		// end - 每一次数组最后一个元素的下标
		// InsertNum - 要插入的元素
		int end = i - 1; 
		int InsertNum = a[i];
		
		while (end >= 0)
		{
			// 如果插入的元素比当前元素小,就要往后挪动数据
			if (a[end] > InsertNum)
			{
				a[end + 1] = a[end];
				end--;
			}
			// 插入比当前元素大,则直接插入
			else
			{
				break;
			}
		}
		// 当循环结束后,存在两种情况
		// 1. 头插
		// 2. break跳出来的 
		// 以上情况直接插入即可
		a[end + 1] = InsertNum;	
	}
}

【运行结果】

在这里插入图片描述

四、特性总结

  1. 时间复杂度

最好情况:原数组已经是按需求有序了,每趟只需与前面的有序元素序列的最后一个元素进行比较,总比较次数为n - 1,时间复杂度为 O(N);

最坏情况:假设要排升序,原数组是逆序的情况下,O(N2)

综上,直接插入排序的时间复杂度为O(N2)

  1. 空间复杂度

O(1)。只用到了一个数组

  1. 稳定性

插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。如果碰见一个和插入元素相等的,那么将会把待插入元素放在相等元素的后面。所以,相等元素的相对的前后顺序没有改变,所以插入排序是 稳定 的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值