十大排序算法(三 :插入)

思想

        插入排序和选择排序有一个异曲同工的地方在于他们都存在一个:在原数组上创建子数组的思想,这两种排序方法都会将原数组分为两个部分:待排序数组与已排好序的数组,但是这两种算法的内核思想却截然不同,现在我们来理解一下插入排序是怎么实现的。

       首先我们得到了一个无序的数组,现在我们将这个数组视为两部分,无序数组和已排好序的数组:

        蓝色部分代表未排好序的数组,而绿色部分代表已排好序的数组,这两个数组都位于这个全部的数组之上,当然现在全部数组都是一个无序数组,因此我们看不见绿色,整个数组都是蓝色的,但是我们可以想想:在数组的首元素之前,有一个虽然不存在,但是在概念上存在的有序数组区域,它一直存在,只不过它现在是空的而已,接下来我们要做的,就是从无序数组中取得元素,并插入到这个有序数组中去。

​        如下图所示,我们拿到了无需数组中的第一个元素:6,并将其插入到有序数组中去,此时有序数组中什么都没有,因此不需要对6这个元素进行任何操作,直接放进去,这个有序数组的有序性没有被改变,其仍是一个有序数组,因为只有一个元素的数组,谈不上有没有顺序概念,我们完全可以将其视为一个有序数组:

        现在,有序数组和无序数组的分解开始显现出来了,现在我们继续从无序数组中取值,并放进无序数组中去。不同的是,这次,我们取到的数字是1,我们如果直接将1放进有序数组是不行的,因为直接放进去的话会导致有序数组变为无序数组:

​        因此我们需要让1进行移动,让它在有序数组中进行移动,直到它移动到合适自己的位置即可,因为我们已知有序数组是有序的,因此对于新加进来的元素1,我们应该让它开始和有序数组中的最后一个元素开始往前进行比较,直到找到了一个比它还小的元素后才停止,这里,1应该移动到6前边:

        这样一来有序数组就又变得有序了,之后我们继续将无序数组的元素向有序数组中加,下一个元素是9,我们在经过对比后,发现9是大于当前有序数组的最后一个数字6,因此9无需前移:

        我们继续将无序数组中的元素往有序数组中放,这次我们取得的元素是2,我们发现2是比当前有序数组的最后一个数组小的,因此要往前移动一次,在移动一次之后,我们发现2仍然比它前一个元素小,因此这时2仍然会使这个有序数组变得无序,因此我们还需要让2进行前移,现在2移动到了1后边,经过对比我们发现2比1大,这时2无需继续移动了,因此此时数组是这样:

        我们继续重复上面的行为,发现了下一个要加入有序数组中的数字为3,同样,我们重复上述的对比行为,如果3前边的数字比3大,就要将它往前移动,因此在移动好之后,我们会得到这样的数组:

        下一个数字是7,我们现在要将7放入到有序数组中去,7放到有序数组中之后要开始和它前边的元素进行对比,发现当前7前边的数字是9,因此7需要往前移动,移动之后,我们发现7前边的数字是6,这时7大于6,因此不再需要移动了:

        我们继续从无序数组中向有序数组中插入元素,发现下一个是19,显然插入19之后,我们发现19大于其前边的元素值:9,因此19不需要进行前移了:

        现在我们继续将无序数组中的元素向有序数组中插入,发现此时无序数组中还剩一个:15,因此我们将其插入到有序数组的尾部,这时我们发现15比它前边的数字19小,因此15需要往前移动,在移动之后我们会发现15后边的数字是9,这是15大于9,因此15遍不再需要移动了,而这时无序数组也从原数组空间上消失了,整个数组变成了一个有序数组:

动图

 代码实现

#include <bits/stdc++.h>
using namespace std;
int n,a[100];
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
	}
	for(int i=1;i<n;i++)
	{
		for(int j=i-1;j>=0;j--)
		{
			if(a[j]>a[j+1])
			{
				swap(a[j],a[j+1]);
			}
			else
			{
				break;
			}
		}
	}
	for(int i=0;i<n;i++)
	{
		cout<<a[i]<<" ";
	}
	return 0;
}
时间复杂度
  1. 最坏情况下:O(n^2)
  2. 最好情况下:O(n) (有序情况下)
空间复杂度

O(1)

稳定性

稳定

是不是和冒泡排序有点像?它们可完全不一样!!!

十大排序算法(上)就讲完了,前两篇的链接在下方,想看的的可以去看

十大排序算法(一:冒泡排序)-CSDN博客

十大排序算法(二 :选择排序)-CSDN博客

记得点个赞哟!不要当白嫖党!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值