插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

通俗点理解就是:每步将一个待排序的记录,按其顺序码大小插入到前面已经排序的字序列的合适位置(从后向前找到合适位置后),直到全部插入排序完为止。

1.1 算法描述

一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:

  • 从第一个元素开始,该元素可以认为已经被排序;
  • 取出下一个元素,在已经排序的元素序列中从后向前扫描;
  • 如果该元素(已排序)大于新元素,将该元素移到下一位置;
  • 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
  • 将新元素插入到该位置后;
  • 重复步骤2~5。

1.2 动图演示

十大经典排序算法之插入排序(Insertion Sort)_i++

1.3 例题分析

有一数组 int[] arr={3,1,5,4,2};使用插入排序每一趟的结果如下:

---------------------------------------------------------------

第一趟排序: 原始数据:3 1 5 4 2

1比3小,则1和3换位置

排序结果:1 3 5 4 2

---------------------------------------------------------------

第二趟排序: 5比3大,不需要调整

排序结果:1 3 5 4 2

---------------------------------------------------------------

第三趟排序: 4比5小,则4和5 换位置,

此时4比3大,则不再继续调整

排序结果:1 3 4 5 2

---------------------------------------------------------------

第四趟排序: 2比5小,2和5换位置,2又比4小,

2继续和4换位置,2仍然比3小,继续和3换位置,

最后2比1大,不再调整

排序结果:1 2 3 4 5

---------------------------------------------------------------

1.4 代码展示

//定义了一个抽象方法,里面是打印算法排序的通用方法
public abstract class SortBase {
public abstract int[] sort(int[] a);
public static void print(String prefix, int[] arrayForSort) {
System.out.print(prefix + ":");
System.out.print("[");
for (int i = 0; i < arrayForSort.length; i++) {
if (i == arrayForSort.length - 1) {
System.out.print(arrayForSort[i]);
} else {
System.out.print(arrayForSort[i] + " ,");
}
}
System.out.println("]");
}

}
import java.util.Scanner;

public class insertionSort extends SortBase {

public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入元素个数:");
int n = sc.nextInt();
int arr[] = new int[n];
System.out.println("请依次输入元素:");
for (int i = 0; i < arr.length; i++) {
arr[i] = sc.nextInt();
}
insertionSort is = new insertionSort();
is.sort(arr);

}

@Override
public int[] sort(int[] array) {
//打印排序前的初始结果
print("排序前", array);
if (array.length == 0) {
return array;
}
// 从下标为1开始比较,直到数组的末尾
for (int i = 1; i < array.length; i++) {
int j;
// 将要比较的元素存放到临时变量中
int temp = array[i];
// 与前一元素一次比较,如果前一元素比要插入的元素大,则互换位置
for (j = i - 1; j >= 0 && array[j] > temp; j--) {
array[j + 1] = array[j];
}
// 将比较后的元素插入
array[j + 1] = temp;
//打印每一次排序的结果
print("第" + i + "趟排序", array);
}
//打印最终排序的结果
print("排序后", array);
return array;
}

}

1.5 测试案例

十大经典排序算法之插入排序(Insertion Sort)_插入排序_02

1.6 小结

插入排序的时间复杂度 就是判断比较次数有多少,而比较次数与 待排数组的初始顺序有关,当待排数组有序时,没有移动操作此时复杂度为O(N),当待排数组是逆序时,比较次数达到最大--对于下标 i 处的元素,需要比较 i-1 次。总的比较次数:1+2+...+N-1 ,故时间复杂度为O(N^2)