美文网首页
排序算法入门之「插入排序」

排序算法入门之「插入排序」

作者: 码农田小齐 | 来源:发表于2020-10-20 09:45 被阅读0次

插入排序

借用《算法导论》里的例子,就是我们打牌的时候,每新拿一张牌都会把它按顺序插入,这,其实就是插入排序。

齐姐声明:虽然我们用打牌的例子,但是可不能学胡适先生啊。

对于数组来说怎么做呢?

有一个重要的思想,叫做挡板法,就是用挡板把数组分成两个区间:

  • 挡板左边:已排序
  • 挡板右边:未排序

那么排序分三步走:

  1. 最初挡板是在数组的最左边,index = 0 的位置,也就是保证了已排序区间里一个数都没有,或者也可以包含一个数啦;

  2. 核心思想就是:
    依次遍历未排序区间里的元素,在已排序区间里找到正确的位置插入;

  3. 重复这个过程,直到未排序区间为空。

举个例子:{5, 2, 1, 0}

第一步,挡板最初在这里:

第二步,
把 2 插入已排序区间的正确位置,变成:

重复这个步骤,把 1 排好:

最后把 0 排好:

那代码也很简单:

public void insertionSort(int[] input) {
    if (input.length <= 1) {
        return;
    }
    for(int i = 1; i < input.length; i++) {
        int tmp = input[i];
        int j = i - 1;
        while(j >= 0 && input[j] > tmp) {
            input[j+1] = input[j];
            j --;
        }
        input[j+1] = tmp;
    }
}

我们来分析一下这个算法的时空复杂度。

时间复杂度

关于时间复杂度有两个要点

  • 是描述随着自变量的增长,所需时间的增长率;
  • 是渐近线复杂度,就是说
    • 不看系数
    • 只看最高阶项

那么我们关心的 worst case 的情况就是:
如果数组是近乎倒序的,每次插入都要在数组的第一个位置插入,那么已排序区间内的所有的元素都要往后移动一位,这一步平均是 O(n),那么重复 n 次就是 O(n^2).

空间复杂度

重点是一个峰值的概念,并不是累计使用的空间。
这里是 O(1) 没什么好说的。

引入一个概念:sorted in place,也就是原地排序

原地排序就是指空间复杂度为 O(1) 的算法,因为没有占用额外的空间,就是原地打转嘛。

其实 in-place 的思想并不是只在排序算法里有,只不过排序算法是一个最广为人知的例子罢了。本质上就是一个节省使用空间的思想。

但是对于排序算法,只分析它的时空复杂度是不够的,还有另外一个重要指标:

稳定性

这个是排序算法的一个重要指标,意思是元素之间的相对顺序是否保持了不变。

比如说:{5, 2, 2, 1, 0}

这个数组排序完成后这里面的两个 2 的相对顺序没有变,那么这个排序就是一个稳定排序。

那有同学可能就想,顺序变了又有什么关系呢?

其实,在实际工作中我们排序的对象不会只是一个数字,而是一个个的对象 (object),那么先按照对象的一个性质来排序,再按照另一个性质来排序,那就不希望原来的那个顺序被改变了。好像有点抽象,我们举个例子。

比如在股票交易系统里,有买卖双方的报价,那是如何匹配的呢?

  • 先按照价格排序;
  • 在相等的价格中,按照出价的时间顺序来排序。

那么一搬来说系统会维持一个按时间排序的价格序列,那么此时只需要用一个具有稳定性的排序算法,再按照价格大小来排序就好了。因为稳定性的排序算法可以保持大小相同的两个对象仍维持着原来的时间顺序。

那么插入排序是否是稳定性的排序呢?答案是肯定的。因为在我们插入新元素的时候是从后往前检查,并不是像打牌的时候随便插一个位置不能保证相对顺序。

大家可以看下下面的动画 就非常清楚了~

优化

插入排序其实是有很大的优化空间的,你可以搜一下“希尔排序”。

在刚开始学习的时候,深度固然重要,但因为广度不够,如果学的太深可能会很痛苦,一个知识点就无穷无尽的延展,这并不是一个高效的学习方式。

所以如果时间有限,就要做好深度和广度的平衡:

  • 在常用常考的知识点上多花时间精力,追求深度;
  • 在一些拓展性的知识点上点到为止,先知道有这么回事就行。

保持 open minded 的心态,后期就会有质的提高。

如果你喜欢这篇文章,记得给我点赞留言哦~你们的支持和认可,就是我创作的最大动力,我们下篇文章见!

我是小齐,纽约程序媛,终生学习者,每天晚上 9 点,云自习室里不见不散!

更多干货文章见我的 Github: https://github.com/xiaoqi6666/NYCSDE

相关文章

  • 算法入门——插入排序、快速排序

    上篇文章学习了算法入门——冒泡排序、选择排序,这篇文章我们学习算法入门——插入排序。 插入排序 插入排序是在一组列...

  • 经典排序算法总结

    经典排序算法集锦 冒泡法 排序算法入门之冒泡排序 排序算法入门之冒泡排序优化

  • 算法-插入排序

    算 法:插入排序算法时间复杂度: 插入排序算法描述 插入排序伪代码 插入排序实现 插入排序算法概述 插入排...

  • 算法入门——堆排序

    上篇文章我们学习了算法入门——插入排序、快速排序,这篇文章我们学习算法入门——堆排序。 堆 堆是一种特殊的完全二叉...

  • c算法O(n)^2(一)

    选择排序 插入排序 优化插入排序算法

  • 排序算法之插入排序和希尔排序(shell sort)

    插入排序(inserction sort)和希尔排序(shell sort) 相关文章 排序算法之快速排序

  • python 冒泡排序和选择排序算法

    插入排序算法 冒泡排序算法

  • Chapter 2 Foundation of Algorith

    Chapter 2 插入排序 线性查找 选择算法 归并排序算法 二分查找算法 冒泡排序 插入排序 循环不...

  • 排序

    本文记录几个基础的排序算法。排序算法分为插入排序、交换排序、选择排序等几大类。 插入排序 1. 直接插入排序 O(...

  • 排序算法入门之「插入排序」

    插入排序 借用《算法导论》里的例子,就是我们打牌的时候,每新拿一张牌都会把它按顺序插入,这,其实就是插入排序。 齐...

网友评论

      本文标题:排序算法入门之「插入排序」

      本文链接:https://www.haomeiwen.com/subject/veirmktx.html