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

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

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

一.直接插入排序

(一)不带哨兵

以下按从小到大排序演示

1.原序列:0号位的49做为已完成排序的子序列,后面将1-7号位的元素依次插入到前面
8-1插入排序-直接插入排序_第1张图片
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;
8-1插入排序-直接插入排序_第2张图片
处理完成
8-1插入排序-直接插入排序_第3张图片
3.处理2号位的记录65
49<65,保持不变
8-1插入排序-直接插入排序_第4张图片
完成
8-1插入排序-直接插入排序_第5张图片
4.以此类推,当处理5号位的13时
13<97,97后移
13<76,76后移
13<65,65后移
13<49,49后移
13<38,38后移
13插入0号位
8-1插入排序-直接插入排序_第6张图片
代码角度:

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
		}

完成
8-1插入排序-直接插入排序_第7张图片
5.以此类推,处理7号位的49时
将已排好序的子序列中大于49的后移,即456号位的记录后移,49插入4号位

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

因此,直接插入排序是稳定的
8-1插入排序-直接插入排序_第8张图片
完整代码(C++)

#include
#include
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–)
8-1插入排序-直接插入排序_第9张图片
完整代码

#include
#include
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]对比
8-1插入排序-直接插入排序_第10张图片
以此类推
8-1插入排序-直接插入排序_第11张图片
最坏时间复杂度=O((2+3+…+n)+(3+4+…+n+1))=O(n²)
(3)平均时间复杂度:O(n²)

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

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

你可能感兴趣的:(数据结构,排序算法,算法,数据结构)