基本思想:每趟将一个元素,按其关键字大小,插入到它前面已排序的子序列中,使得插入后的子序列仍是排序的,一次重复直到全部元素插入完毕。
插入排序算法有三种:直接插入排序、折半插入排序和希尔排序。
1.直接插入排序算法描述:
a.第i(1<=i<n)趟,数据序列为{a0,a1,...,ai-1,ai,...,an-1},其前i个元素构成子序列{a0,a1,...,ai-1}是排序的,将元素ai插入到子序列{a0,a1,...,ai-1}的适当位置,使插入后的子序列仍然是排序的,ai的插入位置由关键字比较决定。
b.重复上述操作,n个元素共需n-1趟扫描,每趟将一个元素插入到它前面的子序列中。
关键字序列{32,26,87,72,26*,17}的直接插入排序(升序)过程如下图
上述序列中有两个相同关键字,以*区别。围排序时,关键字26在26*之前,排序后,26仍在26*之前。因此直接插入排序算法是稳定的。
2.直接插入排序算法实现
package cn.crazyguan.Sort;
/**
*
* @author guan
* @description Insertion Sort implements by Array
*/
public class InsertionSort {
/**
* @function 产生n个随机数,返回整数数组
* @param n 随机数组长度
* @return 生成的随机数组
*/
public static int[] random(int n){
if(n>0){
int table[] = new int[n];
for(int i =0;i<table.length;i++){
table[i] = (int) (Math.random()*100);
}
return table;
}
return null;
}
/**
* @function 打印数组
* @param table
*/
public static void print(int[] table){
for(int i =0;i<table.length;i++){
System.out.print(table[i]+" ");
}
System.out.println();
}
/**
* @fucntion 直接插入排序,数组是引用类型,元素值将被改变
* @param table
*/
public static void insertSort(int[] table){
for(int i =1;i<table.length;i++){
int temp = table[i],j;
for(j =i-1;j>-1&&temp<table[j];j--){
table[j+1] = table[j];
}
table[j+1] = temp;
System.out.print("第"+i+"趟");
print(table);
}
}
public static void main(String[] args){
int[] table = InsertionSort.random(8);
System.out.print("关键字序列:");
InsertionSort.print(table);
InsertionSort.insertSort(table);
}
}
其中,random(n)方法生成一个由n个随机数组成的数组,返回整数数组,print(table[])方法输出所有数组元素值;insertSort(table[])方法实现直接插入排序算法,由于数组是引用类型,元素值将改变。该方法中,在循环for(j=i-1;j>-1&&tamp<=table[j];j--)中,关键字相等时,前面元素也向后移动,导致排序算法不稳定。
3.直接插入排序算法分析
设数据序列有n个元素,直接插入排序算法执行n-1趟,每趟的比较次数和移动次数与数据序列的初始排列有关。以下分最好、最坏和随机三种情况分析直接插入排序算法的时间复杂度。