基本思想:
有一个待排序的数组,数组的第一个元素默认为有序的,从第二个元素开始,每个元素都和前面的有序数组中的元素从后到前依次比较,如果小于前面的有序数组,则将有序数组后移一个位置,反之则所在的位置+1即为新元素要插入的位置。
形象来说就好比如我们玩扑克牌的时候,我们抽取第一张牌的时候不需要进行比较,默认直接放在左手边,左手边的牌是已经排好序的,当我们抽取第二张牌的时候,就和左手边的牌进行比较(实际生活中当我们新抽取一张牌后,我们一般不会从左手最右边的牌开始比较起,而是主观地选择某一个我们可以判断大小的位置接着比较下去,但是反映到程序代码中就要求必须从有序数组的最右边开始比较起,因为程序没有主观判断意识(这里可以注意下,我们可以根据这个思路来对直接插入排序进行优化!)),并插入到合适的位置,使之依旧有序。
java代码实现如下:
package fanzhenhua.sort;
import java.util.Arrays;
public class InsertionSort {
//直接插入排序
public static void insertSort(DataWrap[] data){
int length=data.length;
DataWrap temp=null;
//默认第一个数据为有序的,必须要比较,从第二个数据开始才和前面的有序数组进行比较
for(int i=1;i<length;i++){
//保存有序数组的最后一个索引
int j=i-1;
//保存待插入的值
temp=data[i];
//从有序数组的最后一个数据开始比较,如果大于待插入的数据,则后移一个位置
for(;j>=0&&data[j].compareTo(temp)>0;j--){
data[j+1]=data[j];//后移一位,最后一次移动的元素占两个位置,其中比较靠前的位置为待插入的位置
}
//j+1所在的位置即为待插入元素的位置(之所以需要+1是因为上方的条件判断不符合时,j已经提前减1了)
data[j+1]=temp;
System.out.println(Arrays.toString(data));
}
}
public static void main(String[] args) {
DataWrap[] data = {
new DataWrap(21, "")
,new DataWrap(30, "")
,new DataWrap(49, "")
,new DataWrap(30, "*")
,new DataWrap(16, "")
,new DataWrap(9, "")
};
System.out.println("排序之前:" + Arrays.toString(data));
insertSort(data);
System.out.println("排序之后:" + Arrays.toString(data));
}
}
直接插入排序算法分析:
在最糟糕的情况下,也就是序列逆序排列时(可以理解为每次抽到的新牌相比于有序数组中所有的元素是最小的或者最大的),对于n-1个数中第x个数,每次将该数插入时将引起x-1次数组移动(这里不计算比较时间),求和得到 n(n-1)/2,很明显时间复杂度为O(n2)。
是否为稳定排序:从上面的排序思路我们可以看到,未排序之前A和B有序,排序的过程中A和B的相对位置不会改变,所以直接插入排序是稳定排序。