8-1插入排序-直接插入排序

插入排序:每次将一个元素插入到前面已排好序的子序列中,直到全部插入完成。

插入排序包括:直接插入排序、折半插入排序、希尔排序

一.直接插入排序

(一)不带哨兵

以下按从小到大排序演示

1.原序列:0号位的49做为已完成排序的子序列,后面将1-7号位的元素依次插入到前面

注:如题目无特殊要求,对第一个元素49的处理视为第一趟排序完成,第二趟排序处理38
在这里插入图片描述
2.处理1号元素,比较1号位的38和0号位的49大小关系,38<49,使49后移(到1号位),38插入到0号位
代码角度:
先暂存1号位的38:temp = a[1];
判断与前一个位置的大小关系if (a[i] < a[i - 1])
前一个位置的元素后移a[i - 1+1] = a[i - 1];
38插入0号位:a[i-1] = temp;
在这里插入图片描述
处理完成
在这里插入图片描述
3.处理2号位的记录65
49<65,保持不变
在这里插入图片描述
完成
在这里插入图片描述
4.以此类推,当处理5号位的13时
13<97,97后移
13<76,76后移
13<65,65后移
13<49,49后移
13<38,38后移
13插入0号位
在这里插入图片描述
代码角度:

if (a[i] < a[i - 1])
		{
			temp = a[i];
			for (j = i - 1; j >= 0 && temp < a[j]; j--) //从前一个元素起往前依次检查,原序列中大就后移,小就跳出循环
//当j减为0时,若temp仍小于a[j],0号位元素a[j]后移,j变为-1,跳出循环,在a[j+1]插入temp。如果不加j >= 0,下一轮比较的是a[-1]和temp的关系
				a[j + 1] = a[j];//后移
			a[j + 1] = temp;//j多减了1,j+1插入temp
		}

完成
在这里插入图片描述
5.以此类推,处理7号位的49时
将已排好序的子序列中大于49的后移,即456号位的记录后移,49插入4号位

对于同一记录49,在原序列中49在前,带下划线的49在后。完成排序后仍然保持该顺序,说明该算法的稳定的

因此,直接插入排序是稳定的
在这里插入图片描述
完整代码(C++)

#include<stdio.h>
#include<iostream>
using namespace std;
void InsertSort(int a[], int n) {
	int i,j,temp;
	for (i = 1; i < n; i++) {//从数组为1的记录开始依次插入
		if (a[i] < a[i - 1])
		{
			temp = a[i];
			for (j = i - 1; j >= 0 && temp < a[j]; j--) 
				a[j + 1] = a[j];
			a[j + 1] = temp;
		}
	}
}
int main()//主函数可不写
{
	int a[5] = { 34,23,12,87,45 };
	InsertSort(a, 5);
	for (int i = 0; i <= 4; i++)
	{
		cout << a[i] << " ";
	}
}

(二)带哨兵
序列从1开始存,0作为哨兵,作用充当上面的temp,用于临时存值(a[0] = a[i]),初始默认1为已完成排序的子序列,从2开始插入

优势:因待插入元素存放在a[0],当处理完1,j减为0时,待插入元素和a[0]必然相等,一定会跳出for循环,不用添加限制条件j >= 0

不带哨兵代码:for (j = i - 1; j >= 0 && temp < a[j]; j–)
在这里插入图片描述
完整代码

#include<stdio.h>
#include<iostream>
using namespace std;
void InsertSort(int a[], int n)
{
	int i, j;
	for (i = 2; i <= n; i++)
	{
		if (a[i] < a[i - 1])
		{
			a[0] = a[i];
			for (j = i - 1; a[0] < a[j]; j--)
				a[j + 1] = a[j];
			a[j+1]=a[0];
		}
	}
}
int main()
{
	int a[6] = { 0,34,23,12,87,45 };
	InsertSort(a, 5);//5表示有5个数
	for (int i = 1; i <= 5; i++)//从1开始
	{
		cout << a[i] << " ";
	}
}

(三)复杂度
1.空间复杂度:O(1)
2.时间复杂度=关键字对比+移动元素
(1)最好:初始有序,对比关键字n-1次,无需移动,时间复杂度:O(n)
(2)最坏
例如哨兵
共移动3次:2移到0,80移到2,0移到1
共对比2次:a[0]和a[1]对比,a[0]和a[0]对比
在这里插入图片描述
以此类推
在这里插入图片描述
最坏时间复杂度=O((2+3+…+n)+(3+4+…+n+1))=O(n²)
(3)平均时间复杂度:O(n²)

(4)如果使用链表
移动次数减少,关键字对比次数O(n²),时间复杂度仍为O(n²)

(四)总结
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

卡__卡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值