一、概念
插入排序是把一个数插入到一组有序数列的合适位置。在实际操作中往往把数组的第一个数看作有序数列,依次将后面的数插入到前面有序数列的合适位置。
二、排序过程
假设有一个数组,{99,67,82,43,12,26,18,55},则其从小到大插入排序的执行过程如下:
第一次循环:{99,67,82,43,12,26,18,55}
第二次循环:{99,67,82,43,12,26,18,55}
{67,99,82,43,12,26,18,55}
第三次循环:{67,82,99,43,12,26,18,55}
第四次循环:{67,82,43,99,12,26,18,55}
{67,43,82,99,12,26,18,55}
{43,67,82,99,12,26,18,55}
第五次循环:{43,67,82,12,99,26,18,55}
{43,67,12,82,99,26,18,55}
{43,12,67,82,99,26,18,55}
{12,43,67,82,99,26,18,55}
第六次循环:{12,43,67,82,26,99,18,55}
{12,43,67,26,82,99,18,55}
{12,43,26,67,82,99,18,55}
{12,26,43,67,82,99,18,55}
第七次循环:{12,26,43,67,82,18,99,55}
{12,26,43,67,18,82,99,55}
{12,26,43,18,67,82,99,55}
{12,26,18,43,67,82,99,55}
{12,18,26,43,67,82,99,55}
第八次循环:{12,18,26,43,67,82,55,99}
{12,18,26,43,67,55,82,99}
{12,18,26,43,55,67,82,99}
排序结束。
从上面的排序过程可以看出,插入排序是可以提前结束的,所以理论上,插入排序比选择排序要快。而且插入排序的时间复杂度为O(n*n),是稳定排序。
三、Java代码实现
public class InsertionSort { public void sort(int arr[]){ if (null == arr || arr.length<=1){ return; } int lenrth = arr.length; for (int i=1; i<lenrth; i++){ for (int j=i; j>0&&arr[j-1]>arr[j]; j--){ this.exchange(arr, j-1, j); } } } private void exchange(int[] arr, int i1, int i2){ int i = arr[i1]; arr[i1] = arr[i2]; arr[i2] = i; } }
调用sort方法即可实现插入排序。
四、优化
仔细看看上面的程序,每次比较都要交换一次数据,这是很影响效率的。那么这些交换可不可以省去呢?答案是可以的。
下面是优化之后的代码:
public class InsertionSort { public void sort(int arr[]){ if (null == arr || arr.length<=1){ return; } int lenrth = arr.length; for (int i=1; i<lenrth; i++){ int pacemaker = arr[i]; int j; for (j=i; j>0&&arr[j-1] > pacemaker; j--){ arr[j] = arr[j-1]; } arr[j] = pacemaker; } } private void exchange(int[] arr, int i1, int i2){ int i = arr[i1]; arr[i1] = arr[i2]; arr[i2] = i; } }