数据结构->排序->插入排序


排序->内部排序->插入排序

1.直接插入排序

算法思想

​ 每次将一个待排序的记录按照关键字大小插入已排好序的子序列,直到全部记录插入完成。

实现思路(顺序:非递减有序序列)

		1. 记录当前需要排序元素的位置与大小(设位置为 i,大小为min )
		2. 以 i 为分界线,其前为一个有序序列,其后为待排序元素
		3. 将 min 与有序序列中的元素进行比较,直到该元素 <= min,否则将该元素后移。
		4. 将 min 元素放入有序列表
		5. 循环(i++),直到有序

实现代码

点击查看代码
/**
     * 插入排序,最普通的实现方法(还有一种带哨兵的实现方法,就不在此实现了)
     * @param arr
     */
public static void InsertSort(int[] arr){
    for(int i = 1; i < arr.length; i++){
        // 1. 当前需要排列的元素
        int value = arr[i];
        int j;
        // 2. 以当前下标为分界线,前为有序,找到比他更小的元素
        for(j = i-1; j >= 0; j--){
            if(arr[j] <= value){
                break ;
            }
            // 将比它大的元素后移
            arr[j+1] = arr[j];
        }
        // 3. 将元素放在他应在的位置上
        arr[j+1] = value;
    }
}

2.折半插入排序

算法思想

​ 在直接插入的基础上,可以寻找元素在有序表中的位置时使用折半查找的方法,能够减少时间复杂度。

算法思路

​ 同上,但在进行 3 时使用折半查找的方法。

实现代码

点击查看代码
/**
     * 折半插入排序
     *      插入排序的一种优化,同样还有一种带哨兵的实现方法,不再次实现了。
     * @param arr
     */
public static void InsertSortBin(int[] arr){
    for(int i = 1; i < arr.length; i++){
        int value = arr[i];
        int left = 0;
        int right = i-1;
        int mid;
        // 折半查找元素应该在的位置
        while (left <= right){
            mid = (left+right)/2;
            if(arr[mid] <= value){
                left = mid+1;
            }else {
                right = mid-1;
            }
        }

        // 将该位置之后的元素后移
        for(int j = i-1; j >= right+1; j--){
            arr[j+1] = arr[j];
        }
        arr[right+1] = value;
    }
}

3.希尔排序

算法思想

​ 把待排序表分成若干个等长间隔的子表,对每个子表分别进行插入排序,当整个表中的元素都基本有序时,再对全体记录进行一次直接插入排序。

算法思路

​ 1.取一个小于n的步长d1,将表中的元素分为d1组,所以距离为d1的元素放在一个组里;

​ 2.组内进行直接插入排序;

​ 3.取第二个步长d2 < d1,重复上述过程,直到dt = 1,再进行直接插入排序。

​ ps: 到目前为止,还没有得出最优的增量序列(步长序列),希尔提出的方法是每次折半,即d1 = n/2; d2 = d1/ 2,......直到最后增量等于1。

实现代码

点击查看代码
/**
     * 希尔排序
     *  第一个结点暂存元素,不参与排序
     * @param arr
     */
public static void ShellSort(int[] arr){
    for(int d = arr.length/2; d >= 1; d /= 2){
        for(int i = d+1; i < arr.length; i++){
            if(arr[i] < arr[i-d]){
                arr[0] = arr[i];
                int j;
                for(j = i-d; j > 0 && arr[0] < arr[j]; j -= d){
                    arr[j+d] = arr[j];
                }
                arr[j+d] = arr[0];
            }
        }
    }
}

4.其他结论

直接插入排序最坏情况下需要进行的比较次数为:n*(n-1)/2;

直接插入排序属于稳定排序,而希尔排序属于不稳定排序;

直接插入的三种排序方法时间复杂度都为O(n^2);


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM