【七大排序算法】之插入排序(动图,讲解,代码展示)

梦想不抛弃苦心追求的人,只要不停止追求,你们会沐浴在梦想的光辉之中。再美好的梦想与目标,再完美的计划和方案,如果不能尽快在行动中落实,最终只能是纸上谈兵,空想一番。只要瞄准了大方向,坚持不懈地做下去,才能够扫除挡在梦想前面的障碍,实现美好的人生蓝图。【七大排序算法】之插入排序(动图,讲解,代码展示),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文


在这里插入图片描述

一、直接插入排序

1.1概念

把待排序的数字按大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。
比如我们玩扑克牌的时候,就用到了此思想。

1.2图解(动图)

直接插入排序

1.3代码描述

//插入排序
void InsertSort(int* a, int n) {
	for (int i = 0; i < n - 1;i++) {//控制插入个数
		int end = i;
		int tmp = a[end+1];//保存要插入的数据
		while (end>=0) {//排序
			if (tmp<a[end]) {
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;
	}
}

♣①:首先对于单趟的插入,因为是要将一个数插入到一个有序区间中去,假设区间的最后一个位置为(end),那这个待插入数据的位置就是(end+1),因为插入过程中这个数据存在被覆盖的可能,我们先用一个变量tmp保存起来,

♣②:接着将待插入的数据与有序区间的最后一个数进行比较,因为默认选择升序,遇到比tmp大的数据,需要把a[end]往后挪,然后下标往前走,直到(end<0)或者是在中途比较的过程中发现有比待插入数据还要小或者相等的数,就停止比较,跳出这个循环。随着数据的移动,end后一定会空出一个位置,此时执行a[end + 1] = tmp,就可以实现将待插入数据放入有序系列中,并保持这个序列有序。

1.3.1测试用例:

在这里插入图片描述

1.4复杂度及稳定性分析

【时间复杂度】:O(N^2)
【空间复杂度】:O(1)
【稳定性】:稳定
【最好的情况】:序列已经有序,只需要判断是否满足条件,不需要移动,时间复杂度为O(N)。
【中间的情况】数据需要后移一部分,那时间复杂度就是O(N/2)即O(N);
【最坏的情况】,序列是逆序插入,那么每插入一个数据都要和前面的比较、插入N个数据,此时时间复杂度就是O(N^2);
稳定性:稳定性指的是相同两个数,排序后他们的相对顺序不变。上述代码是因为人为改变导致先插入的数据,在后插入数据的后面,不符合稳定性定义,但是通常情况下,直接插入排序是稳定的。

=======================================================
在这里插入图片描述

二、希尔排序( 缩小增量排序 )

2.1概念

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。

2.2图解(动图)

希尔排序
gap越大,后面的数据越容易到前面来,随着gap的减少,gap为1的时候,等同于直接插入排序,这个时候的数据已经接近有序。
请添加图片描述

2.3代码描述

//希尔排序(分组的插入排序)
void ShellSort(int* a, int n) {
	//定义分组程度
	int gap = n;
	while (gap>1)
	{
		//优化速度,gap越大,交换的范围越大,后面的可以更快的到前面,序列会逐渐有序
		
		//保证最后一次是插入排序
		//gap /= 2;//
		gap = gap / 3 + 1;//预排序
		//一位一位走,同时排多个组
		for (int i = 0; i < n - gap;i++) {
			int end = i;
			int tmp = a[end + gap];//保存要插入的数据
			while (end >= 0) {//排序
				if (tmp < a[end]) {
					a[end + gap] = a[end];
					end-=gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
		//6..2..1
		//2..6..1
		//2..1..6
		//1..2..6
		//PrintArray(a,n);
	}
}

♣①:希尔排序看上去和直接插入排序区别不大,它其实隶属于插入排序,直接插入排序间隔为1,希尔排序的间隔(gap)可以控制。

♣②:因为希尔排序的数是被分成了一组一组的,而且每一组的数之间的间隔取决于gap的大小,因此 对于tmp = a[end + gap];,保存的就是当前待比较元素的后移gap位元素,跳出循环之后的tmp也是要放在a[end + gap]的位置。

♣③:当gap越大的时候,后面的可以更快的到前面;当gap越小的时候,间距越小,此时会更进一步得接近有序,但是gap/3之后可能在最后无法使【gap = 1】,那此时的话就需要在最后加上一个1使得最后一次缩小gap增量的时候可以使其到达1。

2.3.1测试用例

我们通过单层gap结束后进行打印再来观察一下希尔排序的数据变化。
在这里插入图片描述

2.4复杂度及稳定性分析

【时间复杂度】:O(NlogN)(O(n^1.3))
【空间复杂度】:O(1)
【空间复杂度】:和插入排序一样,只是在内部定义了一些变量,并没有去申请一些额外的空间,因此空间复杂度为O(1)
稳定性:不稳定,分组排序的时候已经把顺序打乱了
在这里插入图片描述
希尔排序时间复杂度和步长有关。
迄今为止,还无法从理论上精准地分析希尔排序的效率,此处设计数学上难以解决的问题,各位数学好的小伙伴有兴趣可以研究一下🤗,我们姑且认为他的时间复杂度为O(n^1.3)。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/153227.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!