zoukankan      html  css  js  c++  java
  • 排序算法系列:插入排序算法

    概述

    直接插入排序(Straight Insertion Sort)的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。

                               – 《大话数据结构》


    版权说明

    著作权归作者所有。
    商业转载请联系作者获得授权,非商业转载请注明出处。
    本文作者:Coding-Naga
    发表日期: 2016年3月24日
    原文链接:http://blog.csdn.net/lemon_tree12138/article/details/50968422
    来源:CSDN
    更多内容:分类 >> 算法与数学


    目录


    算法原理分析

    从上面的概述中我们也就可以知道了,这里对数组进行排序的过程需要两个序列才能完成。
    一个待排序的乱序序列,一个是已排序的有序序列。我们现在要要做的就是把乱序的元素一个一个地从乱序列中插入到有序序列中去。就像下面这样:
    这里写图片描述
    可是,这里还是有一些不太好的地方,比较明显地方就是我们需要额外添加一个辅助数组。如果这个待排序数据比较大,那么可能添加辅助数组的策略就不能使用了。
    这里我们不难想到,在原始数组中,有这样的一个等式:整体序列 = 有序序列 + 乱序序列
    也就是说我们可以把当前序列数组一分为二,左边为有序,右边为乱序。
    这里写图片描述
    这样每次从乱序序列中取出第一个元素,从有序列中插入。直到序列整体有序为止。具体的步骤请参见下面的算法步骤


    算法步骤

    1. 默认序列中的第0个元素是有序的(因为只有一个元素a[0]嘛,自然是有序的);
    2. 从下标为1(下标从0开始)的元素开始,取当前下标i位置处的元素a[i]保存到一个临时变量waitInsert里;
    3. 对前半部分有序序列的循环遍历,并与waitInsert比较,直到遇到一个比waitInsert小的元素(这里默认是从小到大排序),此时的下标为j,那么现在只要对a[j+1]进行赋值waitInsert即可;
    4. 将待插入元素的下标 i 向后推移一个位置;
    5. 重复进行第2步到第4步,直到乱序序列中的元素被全部插入到有序序列中;
    6. 经过以上5个步骤之后,整体序列必然有序,排序完成。

    逻辑实现

    /*
         * 排序算法的核心模块
         * 
         * @param array
         *      待排序数组
         */
        private void sortCore(int[] array) {
            int arraySize = array.length;
    
            for (int i = 1; i < arraySize; i++) {
                int j = i;
    
                int waitInsert = array[i];
                while(j > 0 && waitInsert < array[j - 1]) {
                    array[j] = array[j - 1];
                    j--;
                }
    
                array[j] = waitInsert;
            }
        }

    复杂度分析

    排序方法 时间复杂度 空间复杂度 稳定性 复杂性
    平均情况 最坏情况 最好情况
    插入排序 O(n2) O(n2) O(n) O(n) 稳定 简单

    这里的最坏的情况和平均情况从代码中就可以看出来,因为有两嵌套的for循环嘛。那么其最好的情况呢?这个就是对于一个有序的序列来说,不需要进行交换,只是比较了n次,所以这里最好的时间复杂度就是O(n)。


    Ref

    • 《大话数据结构》

    Github源码下载

    https://github.com/William-Hai/ArraySortAlgorithm/blob/master/src/org/algorithm/array/sort/impl/InsertSort.java

  • 相关阅读:
    codevs 1102 采药 2005年NOIP全国联赛普及组
    codevs 1058 合唱队形 2004年NOIP全国联赛提高组
    动归题目
    友好城市//未测,不知对错
    codevs 1044 拦截导弹 1999年NOIP全国联赛提高组
    codevs 5294 挖地雷
    codevs 1576 最长严格上升子序列
    [BZOJ3289]Mato的文件管理
    [CodeVS1299]切水果
    [TYVJ1473]校门外的树3
  • 原文地址:https://www.cnblogs.com/fengju/p/6336003.html
Copyright © 2011-2022 走看看