排序 - 直接插入排序

算法

直接插入排序(Straight Insertion Sort)的基本操作:
将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。

注意:
在我们的排序问题中,通常将 数据元素 称为 记录

代码

// 对顺序表 L 作直接插入排序
void InsertSort(PSqlist L)
{
	int i, j;
	for (i = 2; i <= L->length; i++)
	{
		// 需要将 L->r[i] 插入到有序子表
		if (L->r[i] < L->r[i - 1])
		{
			// 设置哨兵
			L->r[0] = L->r[i];
			for (j = i - 1; L->r[j] > L->r[0]; j--)
				// 记录后移
				L->r[j + 1] = L->r[j];
			// 插入到正确位置
			L->r[j + 1] = L->r[0];
		}
	}
}

理解

同样的,我们首先给出如下的顺序表结构:

#include <iostream>
#include <vector>

// 用于要排序数组的个数最大值,可以根据需要修改
#define MAXSIZE 10

typedef struct SqList
{
	int r[MAXSIZE + 1];	// 用于存储要排序数组,r[0]用作哨兵或临时变量
	int length;			// 用于记录顺序表的长度
	// 构造函数,使用vector容器中的值来初始化数组
	SqList(std::vector<int>& arr)
	{
		// 首先将长度置为0
		length = 0;
		// 数组下标首先从1开始
		int index = 1;
		for (auto i : arr)
		{
			r[index] = i;
			length++;
			index++;
			if (index > MAXSIZE)
				break;
		}
	}
}SqList,*PSqlist;

接着给出一个交换函数:

// 交换L中数组r的下标为i和j的值
void swap(SqList* L, int i, int j)
{
	int temp = L->r[i];
	L->r[i] = L->r[j];
	L->r[j] = temp;
}

还有输出的函数:

// 输出数组r中的值
void print(PSqlist L)
{
	assert(L != nullptr);

	for (int i = 1; i <= L->length; i++)
	{
		std::cout << L->r[i] << " ";
	}
	std::cout << std::endl;
}

接着,我们假设初始化的数组为r[6] = {0,5,3,4,6,2}
其中的r[0] = 0是为了作 哨兵 ;
我们的 i 从2开始的意思是我们假设 r[1]=5 是默认有序的,需要从它后面开始判断。

i = 2:
此时 L->r [i] = 3 比 L->r [i-1] = 5 要小,故首先将 3 赋值给 r [0]当作哨兵,以作为后续循环右移的终止条件。接着 j = i-1 = 1 开始向左寻找有序表里的要插入的位置,如果有序表里的值小于了哨兵的值,则该位置就是要插入的位置:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
接着我们就可以进行下一次循环了,后续操作不变。
在这里插入图片描述

测试代码

给出如下测试代码:

#include <iostream>
#include <vector>
#include "SortStruct.h"

using namespace std;

int main()
{
	std::vector<int> ar = {5,3,4,6,2};
	SqList a(ar);
	std::cout << "原始序列为:" << std::endl;
	print(&a);
	InsertSort(&a);
	std::cout << "排序后:" << std::endl;
	print(&a);

	return 0;
}

运行结果

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

复杂度

这个算法从时间复杂度来看,
最好的情况;
给定的序列表本身是有序的,比如拿到的序列是:2,3,4,5,6,这样的话,在第一个循环处L->r[i] < L->r[i - 1] 一直不会进入循环,故只是遍历了一遍数组。
时间复杂度为:O(n);
最坏的情况:
给定的序列表本身是逆序的,比如拿到的序列是:6,5,4,3,2,此时需要比较(n+2)(n-1)/2次,记录的移动次数也达到了最大值:(n+4)(n-1)/2次;
如果排序记录是随机的,根据概率相同的原则,平均比较和移动次数约为(n^2)/4次。
故总的时间复杂度为:O(n^2) ;
空间复杂度:O(1) ;
稳定性:稳定

参考资料

【1】程杰. 大话数据结构. 北京:清华大学出版社,2011:2.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值