程序兵法: Java 源码的插入排序算法 (二)

栏目: 编程工具 · 发布时间: 6年前

内容简介:文章工程:* JDK 1.8

号外:为读者持续整理了几份最新教程,覆盖了 Spring Boot、Spring Cloud、微服务架构等PDF。

获取方式:关注右侧公众号"泥瓦匠BYSocket",来领取吧!

摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢!

《程序兵法: Java 源码的插入 排序 算法 (二)》

文章工程:

* JDK 1.8

* 工程名:algorithm-core-learning

* 工程地址:https://github.com/JeffLi1993/algorithm-core-learning

一、前言

上一讲《程序兵法:Java String 源码的排序算法(一)》讲了什么是选择问题,什么是比较能力。

选择问题,是假设一组 N 个数,要确定其中第 K 个最大值者。算法是为求解一个问题。

那什么是算法?

算法是某种集合,是简单指令的集合,是被指定的简单指令集合。确定该算法重要的指标:

– 第一是否能解决问题;

– 第二算法运行时间,即解决问题出结果需要多少时间;

– 还有所需的空间资源,比如内存等。

很多时候,写一个工作程序并不够。因为遇到大数据下,运行时间就是一个重要的问题。

算法性能用大 O 标记法表示。大 O 标记法是标记相对增长率,精度是粗糙的。比如 2N 和 3N + 2 ,都是 O(N)。也就是常说的线性增长,还有常说的指数增长等

典型的增长率

程序兵法: Java 源码的插入排序算法 (二)

典型的提供性能做法是分治法,即分支 divide and conquer 策略:

1. 将问题分成两个大致相等的子问题,递归地对它们求解,这是分的部分;

2. 治阶段将两个子问题的解修补到一起,并可能再做些少量的附加工作,最后得到整个问题的解。

程序兵法: Java 源码的插入排序算法 (二)

二、排序

程序兵法: Java 源码的插入排序算法 (二)

排序问题,是古老,但一直流行的问题。从 ACM 接触到现在工作,每次涉及算法,或品读 JDK 源码中一些算法,经常会有排序的算法出现。

排序算法是为了将一组数组(或序列)重新排列,排列后数据符合从大到小(或从小到大)的次序。这样数据从无序到有序,会有什么好处?

  • 应用层面:解决问题。
    • 最简单的是可以找到最大值或者最小值
    • 解决”一起性”问题,即相同标志元素连在一起
    • 匹配在两个或者更多个文件中的项目
    • 通过键码值查找信息
  • 系统层面:减少系统的熵值,增加系统的有序度
    (Donald Knuth 的经典之作《计算机程序设计艺术》(The Art of Computer Programming)的第三卷)

通过维基百科查阅资料得到:

在主内存中完成的排序叫做,内部排序。那需要在磁盘等其他存储完成的排序,叫做外部排序 external sorting。资料地址:https://en.wikipedia.org/wiki/External_sorting

上一篇《程序兵法:Java String 源码的排序算法(一)》,讲到了 java.lang.Comparable 接口。那么接口是一个抽象类型,是抽象方法(compareTo)的集合,用 interface 来声明。因此被排序的对象属于 Comparable 类型,即实现 Comparable 接口,然后调用对象实现的 compareTo 方法进行比较后排序。

在这些条件下的排序,叫作基于比较的排序(comparison-based sorting)

三、插入排序

白话文:熊大(一)、熊二、熊三… 按照身高从低到高排队(排序)。这时候熊 N 加入队伍,它从队伍尾巴开始比较。如果它比前面的熊身高低,则与被比较的交换位置,依次从尾巴到头部进行比较 & 交换位置。最终换到了应该熊 N 所在的位置。这就是插入排序的原理。

插入排序(insertion sort)

  • 最简单的排序之一。ps: 冒泡排序看看就好,不推荐学习
  • 由 N – 1 次排序过程组成。
    • 如果被排序的这样一个元素,就不需要排序。即 N =1 (1 – 1 = 0)
    • 每一次排序保证,从第一个位置到当前位置的元素为已排序状态。
  • 如图:每个元素往前进行比较,并终止于自己所在的位置

程序兵法: Java 源码的插入排序算法 (二)

/**
 * 插入排序案例
 * <p>
 * Created by 泥瓦匠@bysocket.com on 19/5/15.
 */
public class InsertionSortingDemo {

    /**
     * 插入排序
     *
     * @param arr 能比较的对象数组
     * @param <T> 已排序的对象数组
     */
    public static <T extends Comparable> void insertionSort(T[] arr) {
        int j;

        // 从数组第二个元素开始,向前比较
        for (int p = 1; p < arr.length; p++) {
            T tmp = arr[p];
            // 循环,向前依次比较
            // 如果比前面元素小,交换位置
            for (j = p; (j > 0) && (tmp.compareTo(arr[j - 1]) < 0); j--) {
                arr[j] = arr[j - 1];
            }
            // 如果比前面元素大或者相等,那么这就是元素的位置,交换
            arr[j] = tmp;
        }
    }

    public static void main(String[] args) {
        Integer[] intArr = new Integer[] {2, 3, 1, 4, 3};

        System.out.println(Arrays.toString(intArr));
        insertionSort(intArr);
        System.out.println(Arrays.toString(intArr));
    }
}

代码解析如下:

  • 从数组的第二个元素,向前开始比较。比第一个元素小,则交换位置
  • 如果第二个元素比较完毕,那就第三个,第四个… 以此类推
  • 比较到最后一个元素时,完成排序

时间复杂度是 O(N^2),最好情景的是排序已经排好的,那就是 O(N),因为满足不了循环的判断条件;最极端的是反序的数组,那就是 O(N^2)。所以该算法的时间复杂度为 O(N^2)

运行 main 方法,结果如下:

[2, 3, 1, 4, 3]
[1, 2, 3, 3, 4]

再考虑考虑优化,会怎么优化呢?

插入排序优化版 不是往前比较 。往前的一半比较,二分比较会更好。具体代码,可以自行试试

四、Array.sort 源码中的插入排序

上面用自己实现的插入算法进行排序,其实 JDK 提供了 Array.sort 方法,方便排序。案例代码如下:

/**
 * Arrays.sort 排序案例
 * <p>
 * Created by 泥瓦匠@bysocket.com on 19/5/28.
 */
public class ArraysSortDemo {

    public static void main(String[] args) {

        Integer[] intArr = new Integer[] {2, 3, 1, 4, 3};

        System.out.println(Arrays.toString(intArr));
        Arrays.sort(intArr);
        System.out.println(Arrays.toString(intArr));
    }
}

运行 main 方法,结果如下:

[2, 3, 1, 4, 3]
[1, 2, 3, 3, 4]

那 Arrays.sort 是如何实现的呢?JDK 1.2 的时候有了 Arrays ,JDK 1.8 时优化了一版 sort 算法。大致如下:

  • 如果元素数量小于 47,使用插入排序
  • 如果元素数量小于 286,使用快速排序
  • Timsort 算法整合了归并排序和插入排序

程序兵法: Java 源码的插入排序算法 (二)

源码中我们看到了 mergeSort 里面整合了插入排序算法,跟上面实现的异曲同工。这边就不一行一行解释了。

五、小结

算法是解决问题的。所以不一定一个算法解决一个问题,可能多个算法一起解决一个问题。达到问题的最优解。插入排序,这样就这么简单

资料:

* 《数据结构与算法分析:Java语言描述(原书第3版)》

* https://www.cnblogs.com/vamei/tag/%E7%AE%97%E6%B3%95/

程序兵法: Java 源码的插入排序算法 (二) (关注微信公众号,领取 Java 精选干货学习资料) (添加我微信:bysocket01。加入纯技术交流群,成长技术)


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Data Structures and Algorithms in Python

Data Structures and Algorithms in Python

Michael T. Goodrich、Roberto Tamassia、Michael H. Goldwasser / John Wiley & Sons / 2013-7-5 / GBP 121.23

Based on the authors' market leading data structures books in Java and C++, this book offers a comprehensive, definitive introduction to data structures in Python by authoritative authors. Data Struct......一起来看看 《Data Structures and Algorithms in Python》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

MD5 加密
MD5 加密

MD5 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具