【算法与数据结构习题课笔记】插入排序法

(一)插入排序法:以从小到大排列为例,假设数组arr中[0,i)已排好序,[i,n)还未排序。对于元素arr[i],向前比较元素大小,插入到合适的位置。

 

(二)循环不变量:arr[0...i)已排好序,[i...n)还未排序。把arr[i]放到合适的位置。可以通过交换元素,也可以通过平移元素。

 

(三)具体代码:

只是比较数组中的数字(按从小到大的顺序):

  ①   [0...i)有序,[i...n)无序

    //下面两种写法本质上都是一样的
    public void InsertionSort(int[] arr){
        for (int i = 0;i < arr.length;i ++)
            for (int j = i;j - 1 >= 0;j --)
                if (arr[j - 1] > arr[j])
                    swap(arr,j,j-1);
                else break;
    }

    public void InsertionSort2(int[] arr){
        for (int i = 0;i < arr.length;i ++)
            for (int j = i;j - 1 >= 0 && arr[j - 1] > arr[j];j --)
                swap(arr,j,j-1);
    }

    //交换元素
    public void swap(int[] arr,int i,int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

上面的方法可以实现排序的效果,但一次交换需要三次操作。如果数据量很大的情况下,也是很耗时的,所以我们放弃两两元素交换的做法,采用“先记下当前元素,然后移动元素”的方法:

    public void InsertionSort3(int[] arr){
        for(int i = 0;i < arr.length;i ++){
            int t = arr[i];
            int j;
            for (j = i;j - 1 >= 0;j --)
                if (arr[j - 1] > t)
                    arr[j] = arr[j - 1];
                else break;   
 
                //为什么用break?
                //t前面只要有一个元素小于t,就说明t前面所有的元素都小于t,已经排好序了,就不用再往前比较了

            arr[j] = t;
        }
    }

    //这个写法本质上和上面的相同
    public void InsertionSort4(int[] arr){
        for(int i = 0;i < arr.length;i ++){
            int t = arr[i];
            int j;
            for (j = i;j - 1 >= 0 && arr[j - 1] > t;j --)
                arr[j] = arr[j - 1];
            arr[j] = t;
        }
    }

②   [0...i)无序,[i...n)有序

    public void InsertionSort(int[] arr){
        for (int i = arr.length - 1;i > 0;i --){
            int t = arr[i];
            int j;
            for (j = i;j + 1 < arr.length && arr[j + 1] < t ;j ++)
                arr[j] = arr[j + 1];
            arr[j] = t;
        }
    }

 

比较其他对象(扩展性更强):

public class InsertionSort {
    private InsertionSort(){}

    //更简便,不交换,只平移。
    //[0...i)有序,[i...n)无序
    public static <E extends Comparable<E>> void sort(E[] arr){
        for( int i = 0;i< arr.length;i ++){
            E t = arr[i];
            int j;
            for( j = i;j - 1 >= 0 && arr[j - 1].compareTo(t) > 0;j --)
                arr[j] = arr[j - 1];
            arr[j] = t;
        }
    }

    //[0,i)无序,[i,n)有序
    public static <E extends Comparable<E>> void sort3(E[] arr){
        for(int i = arr.length - 1;i > 0;i -- ){
            E t = arr[i];
            int j;
            for(j = i;j + 1 < arr.length;j ++)
                if( arr[j+1].compareTo(t) < 0)
                    arr[j] = arr[j + 1];
                else break;
            arr[j] = t;
        }
    }
    
    //最好不要这么写,一次交换三次操作,略复杂。
    public static <E extends Comparable<E>> void sort2(E[] arr){
        for(int i = 0; i < arr.length; i ++) {
//            //写法一
//            for( int j = i; j - 1 >=0 ; j-- ){
//                if( arr[ j - 1 ].compareTo(arr[ j ]) > 0 )
//                    swap(arr,j,j-1);
//                else break;
//            }

            //写法二
            for(int j = i;j - 1 >=0 && arr[j-1].compareTo(arr[j]) > 0 ;j --)
                swap(arr,j-1,j);
        }
    }

    public static <E> void swap(E[] arr,int i,int j){
        E temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

}

 

博主也正在学习中,如果有错误或疑问欢迎评论私信交流讨论!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值