#简单算法知识--插入排序

1.1.1插入排序的原理
在这里插入图片描述
通过上面的原理图我们可以看出,直接插入排序的基本操作是将一个记录插入到已经排好的有序表中,从而得到一个新的、记录数增1的有序表。对于给定的一组记录,初始时假定第一个记录自成一个有序序列,其余记录为无序序列。接着从第二个记录开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中,直到最后一个记录插到有序序列中为止。因此,在上图中,插入排序实际上完成插入的轮数为n-1(n为数的个数),从第二行开始进行插入操作,我们可以描述一下这个过程:
在第二轮数据中,通过插入24来组成新的有序数组:[-23,24];
在第三轮数据中,通过在有序数组[-23,24]插入12来组成新的有序数组[-23,12,24];
在第三轮数据中,通过在有序数组[-23,24]插入12来组成新的有序数组[-23,12,24];
以此类推。实际上,插入排序是通过生活中的例子总结而来的,比较熟悉是玩扑克牌,插入排序类似于将抓到的扑克牌插入到现有的扑克牌中,现有的扑克牌是已经排好顺序的,我们从桌子上的牌堆中(按顺序抓下一张牌,而不是随机抓牌)抓牌就好比从原数组中获取数组的紧接着的那一个数字,然后将这张扑克牌插入到左手现有排好顺序的扑克牌中,插排的这个过程就好比从原数组中获取数组的紧接着的那一个数字,并将这个数字插入到现有排好的那一个数组中。
算法分析:
第一轮插入:从原数组取出第二个数arr[1]执行插入,插入的位置取决于第一个数arr[0]的大小,因此这个过程可表示为:
if arr[1] < arr[0]
int temp = arr[1];
arr[1] = arr[0];//将原数组的第一个数向右移动一个位置
arr[0] = temp;
这个过程可表示为:
在这里插入图片描述
第二轮插入:从原数组取出第三个数arr[2]执行插入,插入的位置取决于新数组的第一数arr[0]和第二数arr[1]的大小,因此这个过程可表示为:
//先与第二个数进行比较
if arr[2] < arr[1]
int temp = arr[2];
//将原数组的第二个数向右移动一个位置
arr[2] = arr[1];
arr[1] = temp;
//再与第一个数进行比较
if arr[1] < arr[0]
int temp = arr[1];
//将原数组的第一个数向右移动一个位置
arr[1] = arr[0];
arr[0] = temp;
这个过程可表示为:
在这里插入图片描述
第三轮插入:从原数组取出第四个数arr[3]执行插入,插入的位置取决于新数组的第一数arr[0]和第二数arr[1]和第三个数arr[2]的大小,因此这个过程可表示为:
//先与第三个数进行比较
if arr[3] < arr[2]
int temp = arr[3];
//将原数组的第三个数向右移动一个位置
arr[3] = arr[2];
arr[2] = temp;
//再与第二个数进行比较
if arr[2] < arr[1]
int temp = arr[2];
//将原数组的第二个数向右移动一个位置
arr[2] = arr[1];
arr[1] = temp;
//再与第一个数进行比较
if arr[1] < arr[0]
int temp = arr[1];
//将原数组的第一个数向右移动一个位置
arr[1] = arr[0];
arr[0] = temp;
这个过程可表示为:
在这里插入图片描述
上面的过程我们可以优化为:
int temp = arr[i+1];

while(i>=0 && temp < arr[i]){//注意这里temp不能写成arr[i+1],因为arr[i+1]是动态变化的,而比较插入数据与其他数据的大小时,插入数据是需要保持不变的,因此需要使用一个temp将这个插入数据存储起来,然后再进行比较。
//将原数组的第i+1个数(arr[i])向右移动一个位置
arr[i+1] = arr[i];
i–;
}
//最终是想将循环后的arr[i]与int temp中的arr[i+1]进行替换,但是i=i-1了,因此还需+1(i大于=0是控制元素的下标)
arr[i+1] = temp;

因此,最终插入排序的代码如下所示:
package com.yzh.maven.main;
public class InsertSort {
public static void main(String[] args) {
int[] arr = new int[]{-34,23,5,78,0,-45,90,12,-88,34};
//需要进行n-1轮数据的插入排序
for(int i = 1;i<arr.length;i++){
int j = i-1;
//从第一轮的第二个数开始做插入排序
int insertNum = arr[j+1];
while(j>=0 && insertNum<arr[j]){
//将原数组的第i+1个数(arr[i])向右移动一个位置
arr[j+1] = arr[j];
//继续往前推移
j–;
}
//把插入的数据放在合适的位置
arr[j+1] = insertNum;
}
}
}
对于插入排序的时间复杂度如下所示。
最差情况:反序,需要移动n*(n-1)/2个元素
最好情况:正序,不需要移动元素
数组在已排序或者是“近似排序”时,插入排序效率的最好情况运行时间为O(n);
插入排序最坏情况运行时间和平均情况运行时间都为O(n2)。
因此,一般情况下,插入排序的效率大于选择排序大于冒泡排序。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值