原理:每一步将一个待排序的记录,插入到前面已经排好序的有序序列中去,直到插完所有元素为止。
思想:想必你肯定打过扑克牌吧,在一张一张揭牌的时候,是不是每次揭一张牌将其插入到其他已经有序的牌中的适当位置,如果你没有这个经历,赶紧约一波小伙伴,斗一把。与选择排序一样,把要排序的数据分为已排序区间和未排序序列。初始已排序区间只有一个元素,就是数组的第一个元素,然后取未排序区间中的元素,在已排序区间中找到合适的插入位置将其插入,并保证已排序区间数据一直有序。重复这个过程,直到未排序区间中元素为空。
插入排序有一个关键的点,就是在上图中第四行,当要把3插入到有序序列中的时候,会涉及到移动4,5,6这三个数的操作,插入三需要移动三个数,即4,5,6 ,这样的顺序称为倒置,即逆序,意思是这两个数的顺序是颠倒的。只有移动完这些与插入元素倒序的数之后,要插入的元素才有位置,在整个插入排序过程中,移动次数等于数组中逆序对的个数,即逆序度,为什么呢,看下图:
/**
* @program: JavaSpecialityDeep
* @author: Mr.Zerah
* @create: 2018-10-26 00:45
* @description: 插入排序
**/
public class InsertionSort {
public void insertSort(Comparable[] arr,int N){
//将arr[]按升序排列
for (int i = 1; i < N; i++) {
//将a[i]插入到a[i-1],a[i-2],a[i-3] 之中
for (int j = i; j >0 && SortUtil.less(arr[j],arr[j-1] ); j--) {
SortUtil.exchange(arr, j, j-1);
}
}
}
}
时间复杂度:
如果数组已经是有序的,不需要移动任何数据,因此最好的时间复杂度为O(n);
如果数组是倒叙的,每次插入元素相当于在数组的第一个位置插入新的数据,因此需要大量移动数据,所以时间复杂度为O(n2)。
所以平均时间复杂度为:O(n2)。
参考:《算法4》
极客时间:数据结构与算法之美:https://time.geekbang.org/column/126