插入排序 --- Java版

作者: Skymiles | 来源:发表于2017-01-25 18:15 被阅读59次

算法思路

插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。 非常类似于打牌时候一边抓牌一遍理牌的情形。
插入排序方法分直接插入排序和折半插入排序两种,这里只介绍直接插入排序。
  文字说比较抽象, 下面有个动态图链接🔗帮助理解:
插入排序动态演示图

算法实现

public class InsertionSort {

    public static void sort(Comparable[] a) {
        int N = a.length;
        for (int i = 0; i < N; i++)    // i表示现在正在遍历元素的下标
            //从遍历的那个元素开始向前进行比较,碰到比之前一个元素小就交换,
            //不然直接break(因为左边区域已经有序,若a[j]比a[j-1]大那么一定比a[j-2],a[j-3]...大,那就不用比较交换了)
            for (int j = i; j > 0; j--)    
                if (less(a, j, j - 1))
                    swap(a, j, j - 1);
                else
                    break;
    }

    private static boolean less(Comparable[] a, int i, int j) {
        if (a[i].compareTo(a[j]) < 0)
            return true;
        else
            return false;
    }

    private static void swap(Comparable[] a, int i, int j) {
        Comparable t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
}

性能分析

  首先给一个前提,插入排序性能是有最好情况和最坏情况的,不一样。
  那哪种情况是最好情况?相信你猜出来了就是已经有序的待排数组的情况。如果数组已经有序, 那么看代码,里层循环永远不会执行(会执行break语句),所以只有外层循环起作用那么时间复杂度就是O(N)
  那哪种情况是最好情况?相信你也猜出来了就是完全逆序的待排数组的情况。数组完全逆序,插入第2个元素时要比较交换前1个元素,插入第3个元素时,要比较交换前2个元素,……,插入第N个元素,要比较交换前 N - 1 个元素。因此,最坏情况下的比较次数是 1 + 2 + 3 + ... + (N - 1),等差数列求和,结果为 N^2 / 2,所以最坏情况下的时间复杂度为 O(N^2)。空间复杂度则很直观O(1)。
  综上所述,通过某些数学证明(我目前不懂那个证明,还请网友告知)已经证明出,对于一个完全random且元素不重复的带排序数组,用插入排序平均需要 ¼ N^2 次比较和¼ N^2 交换操作。
  我大概只能从下面这张插入排序步骤图大概看出¼ N^2 这个数字的来源。因为每行灰色的是每次都不移动已经排序好的元素,黑色的是移动的元素,可以看出移动的元素面积大概是所有面积的1/4,这就是平均需要 ¼ N^2 次比较和¼ N^2 交换操作的直观证明。(但是我不知道怎么具体证明......)

algorithm4_princeton

拓展

  如果数组中倒序的元素数量小于数组大小的某个倍数,那么我们就说这个数组部分有序
有几种典型的部分有序数组:

  • 数组中每个元素距离它最终位置不远;
  • 一个基本有序的大数组接一个无序小数组;
  • 数组中只有几个元素位置不对;
    这些数组都适合用插入排序。

  逆序对:

对于一个包含N个非负整数的数组A[1..n],如果有i < j,且A[ i ]>A[ j ],则称(A[ i] ,A[ j] )为数组A中的一个逆序对。

inversion_pair.png
比如
上面这个数组就有6个逆序对。
这里有个定理: 插入排序需要的swap操作和数组中逆序对个数是一样的,需要compare操作的个数大于等于逆序对数目,但小于等于逆序对加上数组大小减1。

相关文章

  • Java 实现插入排序

    本文介绍插入排序原理及 Java 语言实现。 目录 插入排序原理 代码实现版本一版本二单元测试 插入排序原理 从第...

  • c++day09

    插入排序基础版(后插1) 插入排序基础版(后插2) 改进 插入排序基础版(前插) 字符数组 ASCII 的 A =...

  • 插入排序 --- Java版

    算法思路 插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。 非常类似...

  • java快速学习排序---插入排序

    1.java实现插入排序 (1)、图解插入排序 (2)、插入排序的思想 (3)、插入排序的代码实现

  • 插入排序算法(Java版)

    插入排序将数组分成已排序和未排序两个部分,每次都抽一个未排序的数出来,跟已排序的部分进行比较,找到合适的位置插入,...

  • 常见排序的java实现

    常见排序的java实现 常见排序java实现 插入排序(二分插入排序) 希尔排序 快速排序(三数中值快排) 冒泡排...

  • (306)排序-java实现的选择/插入/希尔排序

    引言 用java实现的选择排序、插入排序、希尔排序。 代码(java) 运行结果

  • 数据结构&算法(一)

    一、Java实现快速排序算法 二、Java实现折半插入排序算法 三、Java实现冒泡排序算法

  • java 实现排序算法之「插入排序」

    java 实现排序算法系列 这是 Java 实现排序算法的第三篇文章——插入排序算法。插入排序可以说成是「一类」简...

  • 插入排序与希尔排序Java版

    插入排序 时间复杂度:O(n²) 插入排序(Insertion Sort)是一种简单直观的排序算法。它的工作原理是...

网友评论

    本文标题:插入排序 --- Java版

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