插入排序

基本思想(从小到大排序)

1、n个待排序元素看作一个有序表(左),一个无序表(右),初始有序表只含一个元素,无序表含n-1个元素

2、每次从无序表取出第一个元素,把它与有序表最后一个元素倒序比较

3、将它插入到有序表适当位置,直到无序表元素为0

 

插入方式

1、直接插入排序:在添加新的记录时,使用顺序查找的方式找到其要插入的位置,然后将新记录插入

2、折半插入排序:使用折半查找来代替顺序查找,减少比较次数

3、2-路插入排序:在折半插入排序的基础上对其进行改进,减少其在排序过程中移动记录的次数从而提高效率

(1)利用一个与排序序列一样大小的数组作为辅助空间,设置 first 和 final 指针标记辅助数组开始位置和最后位置

(2)遍历未排序序列

(3)如果待插入元素比已排序序列最小的元素(first)小,则 first 位置前移,将待排序元素插入 first 位置

(4)如果待插入元素比已排序序列最大的元素(final)大,则 final 位置后移,将待排序元素插入 final 位置

(5)如果待插入元素比最小大,比最大小,则需要移动元素,过程类似直接插入排序,不过考虑到循环使用数组,对于下标的处理有些许不同

(6)处理完最后一个元素后,将排序记录复制到原来的顺序表里

4、表插入排序

(1)1、2、3 基本结构都采用数组的形式进行存储,因而无法避免排序过程中产生的数据移动的问题,如果想要从根本上解决只能改变数据的存储结构,改用链表存储

(2)使用链表的存储结构对数据进行插入排序,在对记录按照其关键字进行排序的过程中,不需要移动记录的存储位置,只需要更改结点间指针的指向

 

代码实现

public class InsertSort {//从小到大排序

    //移动法
    public static void insertSort(int[] array) {
        if (array == null || array.length <= 1) {
            return;
        }
        //有序表在左,无序表在右;有序表第一个元素索引为0,无序表第一个元素索引为1
        for (int i = 1; i < array.length; i++) {//遍历无序表,从索引1到索引array.length-1
            int insert = array[i];//储存无序表第一个元素
            int index = i - 1;//储存有序表最后一位元素的索引
            while (index >= 0 && insert < array[index]) {//index >= 0,保证下标不越界
                array[index + 1] = array[index];//有序表中与insert比较过且大于insert的元素都右移一位
                index--;//从有序表的最后一位元素开始,倒序遍历比较有序表
            }//完全遍历有序表或找到比insert大的元素就退出循环
            array[index + 1] = insert;//index = -1,insert插入有序表第一位;或插入第一个比insert小的元素的右一位
        }
    }
    
    //省略交换法的实现,时间:交换法 > 移动法,因为访问数组的次数更少
}

 

对于随机排列的长度为 N 且主键不重复的数组

1、比较的总次数是交换的次数加上一个额外的项,该项为 N 减去被插入的元素正好是已知的最小元素的次数

(1)在最坏情况下(逆序数组),这一项相对于总数可以忽略不计

(2)在最好情况下(数组已经有序),这一项等于 N-1

2、插入排序所需的时间取决于输入中元素的初始顺序

(1)对一个很大且其中的元素已经有序(或接近有序)的数组进行排序,将会比对随机顺序的数组或是逆序数组进行排序要快得多

(2)插入排序对一个有序数组进行排序时,能够立即发现每个元素都已经在合适的位置之上,它的运行时间也是线性的

(3)插入排序对于部分有序的数组十分高效,也很适合小规模数组

3、部分有序的数组

(1)数组中倒置的数量小于数组大小的某个倍数

(2)倒置指的是数组中的两个顺序颠倒的元素

4、典型部分有序数组

(1)数组中每个元素距离它的最终位置都不远

(2)一个有序的大数组接一个小数组

(3)数组中只有几个元素的位置不正确

5、插入排序需要的交换操作 = 数组中倒置的数量,倒置的数量 + 数组大小 - 1 >= 需要的比较次数 >= 倒置的数量

(1)每次交换都改变了两个顺序颠倒的元素的位置,相当于减少了一对倒置,当倒置数量为0 时,排序就完成了

(2)每次交换都对应着一次比较,且 1 到 N-1 之间的每个 i 都可能需要一次额外的比较(在 a[i] 没有达到数组的左端时)

6、大幅提高插入排序的速度,只需要在内循环中将较大的元素都向右移动而不总是交换两个元素,这样访问数组的次数就能减半

7、对于随机排序的无重复主键的数组,插入排序和选择排序的运行时间是平方级别的,两者之比应该是一个较小的常数

posted @   半条咸鱼  阅读(18)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示