1.原理
直接插入排序原理和插牌方法类似,它将数组看作有序元素和无序元素组成的数组,把无序的元素插入到有序的数组中。
已知待排序数组a=[4,2,1,3].
综述:2为待插入数,4>2,变为[2,4,1,3]; 1为待插入数,4>1和2,变为[1,2,4,3]; 3为待插入数,4>3,3>1和2,变为[1,2,3,4].
第一次排序:
有序元素:[4],待插数:2
抓到2,因为4>2,将4后移,即a[1]=4;
[4,4]
再将2插到a[0]中,即a[0]=2;
[2,4]
第二次排序:
有序元素:[2,4],待插数:1
抓到1,因为4>1,将4后移,即a[2]=4;
[2,4,4]
因为2>1,将2后移,即a[1]=2;
[2,2,4]
再将1插入到a[0]中,即a[0]=1;
[1,2,4]
第三次排序:
有序元素:[1,2,4],待插数:3
抓到3,因为4>3,将4后移,即a[3]=4;
[1,2,4,4]
因为2<3,无需将剩余有序数组元素和3比较,将3插入到a[2],即a[2]=3;
[1,2,3,4]
2.时间复杂度
最好情况:序列是升序排列,在这种情况下,需要进行的比较操作为(n-1)次,交换操作为0次,即O(n)。
最坏情况:序列是降序排列,那么此时需要比较n(n-1)/2次,交换操作(n+2)(n-1)/2次,即O(n^2)。
注:例如654321,需要将它排为654321,则只需要比较5次;当将它排为123456时,就要比较1+2+3+4+5次,移位2+3+4+5+6次。
3.代码实现
1 public class InsertSortTest { 2 //遍历数组 3 public static void cc(int a[]){ 4 for(int i=0;i<a.length;i++){ 5 System.out.print(a[i]+" "); 6 } 7 System.out.println(); 8 } 9 public static void Test(int a[]) { 10 for (int i = 1; i < a.length; i++) { //从第二个数开始 11 int temp = a[i]; //设置待插入数 12 int j = i - 1; 13 while (j >= 0 && a[j] > temp) { //将待插入的数和前面的有序数组元素进行比较 14 a[j + 1] = a[j]; //如果前面的有序数组元素大于待插入数,则将有序数组元素后移 15 InsertSortTest.cc(a); 16 j--; 17 } 18 a[j + 1] = temp; //如果某有序数组元素小于待插入数,终止后移,并且在该元素后插入待插入数 19 InsertSortTest.cc(a); 20 } 21 } 22 public static void Test1(int a[]) { 23 for (int i = 1; i < a.length; i++) { 24 int temp = a[i]; 25 while (i >= 1 && a[i-1] > temp) { 26 a[i ] = a[i-1]; 27 i--; 28 } 29 a[i] = temp; 30 } 31 } 32 public static void Test2(int a[]) { 33 for (int i = 1; i < a.length; i++) { 34 int temp = a[i]; 35 int j=i-1; 36 for(;j>=0;j--){ 37 if(a[j] > temp){ 38 a[j + 1] = a[j]; 39 InsertSortTest.cc(a); 40 } 41 else{ 42 break; 43 } 44 } 45 a[j+1] = temp; 46 InsertSortTest.cc(a); 47 } 48 } 49 public static void main(String[] args) { 50 int a[]={4,2,1,3}; 51 InsertSortTest.Test(a); 52 } 53 }