插入排序

众所周知,插入排序是简单排序三剑客之一 ,它也是我们平时用的最多的简单排序算法之一,今天我们就来一窥究竟。
插入排序故名思意就是插入,但是要将数插入到哪里呢?接下来来看个例子。
例:原数组{5,4,6,1,3,2}从小到大排序
第一轮 5和4比较 4小 交换 变成
4,5,6,1,3,2
第二轮 6和5比较 6大 不做操作直接进入下一轮
4,5,6,1,3,2
第三轮 1和6比较 1小 所以1和6交换位置 ,然后1在和前面的5比,比5小在交换,以此类推。
1,4,5,6,3,2
剩下两轮我就直接写答案了
第四轮
1,3,4,5,6,2
第五轮
1,2,3,4,5,6
接下来让我写代码实现下,既然又涉及到了比较和交换,我就直接拿冒泡排序那一章的的比较和交换方法了,直接放到下面了,不懂的可以去看这里https://blog.csdn.net/hyj393837/article/details/105470476。

/**
	 * 比较
	 * @param val1
	 * @param val2
	 * @return
	 */
	public static boolean compare(Comparable val1,Comparable val2) {
		return val1.compareTo(val2) > 0;
	}
	/**
	 * 交换
	 * @param var
	 * @param i
	 * @param j
	 */
	public static void exchange(Comparable[] var,int i ,int j) {
		Comparable temp = var[i];
		var[i] = var[j];
		var[j] = temp;
	}

第一轮代码

Comparable[] var = {5,4,6,1,3,2};
//第一轮排序
for(int j=1;j>0;j--) 
	if(compare(var[j-1],var[j]))
		exchange(var,j-1,j);

因为比较n-1轮所以直接循环n-1轮就可以了,又因为每轮开始的数组索正好是每轮的轮数 也就是j应该等于i 看下面代码

		for(int i = 1;i< var.length;i++)
			for(int j=i;j>0;j--)
				if(compare(var[j-1],var[j]))
					exchange(var,j-1,j);

看上面你已经可能发现了一个小错误,虽然并不影响了结果,但是已经影响了性能。
好了直接说了们就是 每次我们要比较的数大于已排序号数组的最大的一个数的时候,上面的代码还是去比较。
例如上面的第二轮 6已经比已排序数组中(加粗的数字)最大的值5还大,所以和5比完之后就没有必要在和4比较了,肯定会比4大,所以我们就可以直接跳出循环了
所以我们将代码整理成下面这样

for(int i = 1;i< var.length;i++) 
			for(int j=i;j>0 && compare(var[j-1],var[j]);j--)				
					exchange(var,j-1,j);

总结
1.插入排序每次交换不需要额外空间是原地排序
2.插入排序每轮是从后往前比较,只有比它小才排到前面去,相等的还是会在后面,所以是稳定排序
3.时间复杂度
(1)最好情况下,也就是顺序, 例如{1,2,3,4,5,6},数组不需要交换,只是遍历轮数即可 时间复杂度O(n)。
(2)最坏情况下,也就是逆序,例如{6,5,4,3,2,1},数组每轮都要交换n(不去细致推到了,反正不会超过n,应该是1~n-2,这里就取n了)次,在成于轮数,所以时间复杂度就是 O(n2)。
(3)平均情况下,我们每次插入数据的时间复杂度是O(n),因为要循环执行n次,所以就是O(n2)。
一句话总结,插入排序和冒泡排序一样,都是时间复杂度为O(n2)的原地排序算法
思考???
这样写插入排序比以前那样写性能上有提升么?

for(int i = 1; i< var.length; i++) {
			Comparable value = var[i];//要比较数据
			int j = i;
			for(;j > 0 && compare(var[j-1],value); j--)
				var[j]=var[j-1];
			var[j] = value;
		}

将会在下节选择排序中解答,如果想了解优化插入排序的更多算法可以搜索希尔排序

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值