数据结构中常用排序算法

系列文章目录

第一章 插入排序



前言

大家在玩扑克牌时,是否有这样一种情况,我们拿到一张牌时,总是会将这张牌按照从小到大的顺序放在指定的位置,比如我们现在手里有四张牌,分别是2 4 5 9,那么我们抽到第五张牌是3,于是,我们会将这张小瘪三与9比较,发现它比9小,按照道理应该放在9的前面,于是我们再与5比较,还是比5小,放在5的前面,依次类推,直到我们将这张3与2比较,发现它比2大,我们最终就确定了3这张牌在我们手上的位置,也就是放在2的后面。
这其实就是插入排序的一种基本思想,算是插入排序中的一轮,如果我们继续摸牌,然后按照上述做法,就完成了插入排序。


一、插入排序性质

1.时间复杂度O(n^2):插入排序最坏的情况下也就是整个序列逆序的情况,我们插入一个数就需要遍历一次,故最终结果时间复杂度为n的平方。
2.空间复杂度O(1):显然没有多占用其他空间,
3.我们发现序列越是接近有序,并且大的数在后面,小的数在前面,运行效率越高。

二、插入排序原理

1.情况一

比如我们有这么一组数字
在这里插入图片描述
我们将它们当作一组扑克牌来处理,假设我们第一次摸到一张三,然后我们现在去摸第二张牌,发现它是5,于是我们将这个5,与3比较,发现比3小,我们很随意的将它放在了3的后面,然后我们又摸了一张7,发现还是比5小,继续放5后面,然后摸了一张9,发现还是比7小,继续摸到一张3,这个时候的状态应该是这样。除了我们新摸到的牌之外,前面的牌应该都是有序的。
在这里插入图片描述
那我们现在的做法就是将这张新摸到的3与前面的比较,如果比3大,我们直接将被比较的数字往数组后面移动一个,这个时候要注意的是我们需要把这个新摸到的数提前保存,不然就会被9往后移动的时候覆盖,这里我们用end作为9的下标,tmp作为新数字3的下标,比较完成之后,end–,直到找到tmp应该在的位置。于是就有了
在这里插入图片描述
往后移动,把3覆盖,end前移,
在这里插入图片描述
继续与tmp比较,大于tmp的画要向后移动一次,然后end–
在这里插入图片描述
然后,tmp与5比较(未画出),5往后移。
最终得到的结果应该是tmp与3比较,不满足3大于tmp的条件,停止移动
在这里插入图片描述
此时我们只需要将tmp的值保存在end的后面即可。
这就是我们插入排序排一个数字所做的工作。

2.情况二

还有一种情况是我们将tmp与前面所有的数字比较,发现都比tmp大,这个时候end–已经小于0了,比如下面这样,蓝色框代表是空的没数据
在这里插入图片描述
这个时候,我们也是将tmp的放在end+1的位置即可。

二、插入排序实现

#include <stdio.h>
void PrintArr(int a[], int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}
//插入排序,时间复杂度n^2
//最坏:逆序n^2
//最好:顺序n
void InsertSort(int a[], int n)
{
	int i = 0;
	for (i = 0; i < n - 1; i++)
	{
	//插入一个数据需要以下过程
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (a[end] > tmp)
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;//情况一,需要将tmp放在end+1的位置
			}
		}
		//从while循环中自然退出的即为情况2
		//从while循环中break的是情况1
		//两种情况都需要执行相同的操作,即把tmp放在end+1的位置
		//设计很巧妙,减少了代码量
		a[end + 1] = tmp;
	}	
}
void TestInsertSort(int a[], int n)
{
	InsertSort(a,n);
	PrintArr(a, n);
}
int main()
{
	int a[10] = { 1,2,2,6,6,7,5,5,6,0 };
	TestInsertSort(a, 10);
	return 0;
}

总结

这是直接插入排序的方法一种比较简答的排序方法,其思想和扑克牌排序的思想相同,实现起来也比较简单,是一种比较基础的排序方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值