插入排序

情景:对数组 int[] arr = {6,9,5,2,8,7}中的数据 从小到大排序。

思路:在插入排序中,会有一个标记元素,该标记元素左侧的所有元素都是有序的,该元素及其右侧的元素都是无序的。所以在排序中,会将该被标记元素与它左侧的所有元素逐个比较,如果左侧的元素大于等于该被标记元素,则左侧的元素右移;直至不满足该条件为止,然后将标记元素插入左侧元素移动之前的位置。此时,第一趟排序已经完成。然后将被标记元素原来的位置+1,同理,开始第二趟排序。注意,红色元素为被标记元素。

第一趟排序前: 6 9 5 2 8 7   排序后:6 9 5 2 8 7

第二趟排序前: 6 9 5 2 8 7   排序后:5 6 9 2 8 7

第三趟排序前: 5 6 9 2 8 7   排序后:2 5 6 9 8 7 

第四趟排序前: 2 5 6 9 8 7   排序后:2 5 6 8 9 7

第五趟排序前: 2 5 6 8 9  排序后:2 5 6 7 8 9

代码:

/**
 * 插入排序
 * @author D N
 *
 */
public class InsertSort {
    private long[] a; 
    private int nElems;
    
    public InsertSort(int max){
        a = new long[max];
        nElems = 0;
    }    
    
    public void insert(long value){
        a[nElems] = value;
        nElems++;
    }
    
    public void display(){
        for(int j=0;j<nElems;j++){
            System.out.print(a[j]+"   ");
        }
        System.out.println("");
    }
      
    //插入排序算法 
    public void insertSort(){
        int in,out;
        for(out = 1;out < nElems;out++){
            long temp = a[out]; //a[out]是被标记元素,将被标记元素赋予给一个临时变量temp
            in = out;
            //将被标记元素与它左侧的有序元素逐个比较, 如果左侧的元素大于等于被标记元素,则左侧的元素右移,直至不满足这个条件则停止比较移动,并将被标记元素放到这个位置
            while(in > 0 && a[in-1] >= temp){
                a[in] = a[in-1];
                --in;
            }
            a[in] = temp;
        }
     }
}

运行测试代码:

public class SortTest {
    public static void main(String[] args) {
        int maxSize = 10;
        InsertSort arr = new InsertSort(maxSize);
        arr.insert(6);
        arr.insert(9);
        arr.insert(5);
        arr.insert(2);
        arr.insert(8);
        arr.insert(7);
        arr.display();
        arr.insertSort();
        arr.display();
    }
}

运行结果:

6   9   5   2   8   7   
2   5   6   7   8   9   

效率分析:

在第一趟排序中,最多进行了1次比较,第二趟排序中最多进行了2次比较,所以最多进行了N*(N-1)/2次比较,在每趟排序中,发现插入点之前,平均只有一半的数据进行了比较 N*(N-1)/4。需要注意的是,插入排序中,是比较然后复制,而不是交换,复制消耗的时间比交换要少。虽然它的时间复杂度也是O(n2),但是它比冒泡排序要快一倍,比选择排序也快。插入排序应用比较多。

posted @ 2019-01-24 10:23  51life  阅读(...)  评论(... 编辑 收藏