目录

  • 一、前言
  • 二、maven依赖
  • 三、实现
    • 3.1、详解版
    • 3.2、日志精简版
  • 结语

一、前言

  插入排序常见的有两种:直接插入排序二分插入排序,我们上一篇算法已经讲过了直接插入排序,现在我们就来讲另外一个二分插入排序,在做这个之前,我希望大家一定要了解二分查找算法,不然你会恨懵的,这里我也提供地址给大家学习下:

  • 二分查找算法
  • 直接插入排序

二、maven依赖

pom.xml

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.6.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.14</version></dependency>
</dependencies>

三、实现

  插入排序有很多种编码方式实现,我们先看看它的最基本的实现。

3.1、详解版

/*** 二分插入排序(日志的输出只是为了让大家可以看到它排序的逻辑实际中可以去掉)** @param arr int[] arr = new int[]{23, 8, 28, 10, 21, 19, 9};*/
public static void binaryInsertSort(int[] arr) {// 获取数组的长度int len = arr.length;// 遍历数组从索引为1的位置开始,for (int i = 1; i < len; i++) {log.info("-------------------------------------");log.info("第【{}】轮排序前的结果:{}", i, arr);// 定义左边索引int leftIndex = 0;// 定义右边索引int rightIndex = i - 1;// 定义当前要进行插入排序的数据int insertValue = arr[i];log.info("第【{}】轮排序,左边索引【{}】,右边索引【{}】,要插入排序的数据为【{}】", i, leftIndex, rightIndex, insertValue);// 只要左边索引小于等于右边的索引就进行遍历while (leftIndex <= rightIndex) {log.info("左边索引值【{}】 小于等于 右边索引值【{}】", leftIndex, rightIndex);// 获取中间索引值int middleIndex = (leftIndex + rightIndex) / 2;log.info("(左边索引值【{}】+右边索引值【{}】)/2得到中间索引值【{}】", leftIndex, rightIndex,middleIndex);// 判断待插入排序的数据和中间值进行比较if (insertValue >= arr[middleIndex]) {// 修改左边索引leftIndex = middleIndex + 1;log.info("要插入排序的数据【{}】大于等于中间值【arr[{}]={}】,左边索引值(中间索引值【{}】加1)变为【{}】", insertValue, middleIndex, arr[middleIndex], middleIndex, leftIndex);} else {// 修改右边索引rightIndex = middleIndex - 1;log.info("要插入排序的数据【{}】小于中间值【arr[{}]={}】,右边索引值(中间索引值【{}】减1)变为【{}】", insertValue, middleIndex, arr[middleIndex], middleIndex, rightIndex);}}log.info("左边索引值【{}】 大于 右边索引值【{}】,退出内层循环", leftIndex, rightIndex);if (leftIndex == i) {log.info("要插入的位置【{}】和当前位置【{}】一致不用移动数据", leftIndex, i);} else {log.info("数据【arr[{}]】到【arr[{}]】往后移动,即:", leftIndex, i - 1);// 左边索引右边的数据 到 要排序的数据之前的数据 都往后移动一位for (int j = i; j > leftIndex; j--) {log.info("数据【arr[{}]】移动到【arr[{}]】", j - 1, j);// arr[j-1]移动到arr[j]arr[j] = arr[j - 1];}log.info("要插入排序的数据【{}】插入到【arr[{}]】的位置", insertValue, leftIndex);// 要插入排序的数据插入到左边索引的位置arr[leftIndex] = insertValue;}log.info("第【{}】轮排序后的结果:{}", i, arr);}
}public static void main(String[] args) {int[] arr = new int[]{8, 10, 9, 23, 21, 19};log.info("要排序的初始化数据:{}", arr);//从小到大排序binaryInsertSort(arr);
}

运行结果:

要排序的数据:[8, 10, 9, 23, 21, 19]
-------------------------------------
第【1】轮排序前的结果:[8, 10, 9, 23, 21, 19]
第【1】轮排序,左边索引【0】,右边索引【0】,要插入排序的数据为【10】
左边索引值【0】 小于等于 右边索引值【0】
(左边索引值【0】+右边索引值【0】)/2得到中间索引值【0】
要插入排序的数据【10】大于等于中间值【arr[0]=8】,左边索引值(中间索引值【0】加1)变为【1】
左边索引值【1】 大于 右边索引值【0】,退出内层循环
要插入的位置【1】和当前位置【1】一致不用移动数据
第【1】轮排序后的结果:[8, 10, 9, 23, 21, 19]
-------------------------------------
第【2】轮排序前的结果:[8, 10, 9, 23, 21, 19]
第【2】轮排序,左边索引【0】,右边索引【1】,要插入排序的数据为【9】
左边索引值【0】 小于等于 右边索引值【1】
(左边索引值【0】+右边索引值【1】)/2得到中间索引值【0】
要插入排序的数据【9】大于等于中间值【arr[0]=8】,左边索引值(中间索引值【0】加1)变为【1】
左边索引值【1】 小于等于 右边索引值【1】
(左边索引值【1】+右边索引值【1】)/2得到中间索引值【1】
要插入排序的数据【9】小于中间值【arr[1]=10】,右边索引值(中间索引值【1】减1)变为【0】
左边索引值【1】 大于 右边索引值【0】,退出内层循环
数据【arr[1]】到【arr[1]】往后移动,即:
数据【arr[1]】移动到【arr[2]】
要插入排序的数据【9】插入到【arr[1]】的位置
第【2】轮排序后的结果:[8, 9, 10, 23, 21, 19]
-------------------------------------
第【3】轮排序前的结果:[8, 9, 10, 23, 21, 19]
第【3】轮排序,左边索引【0】,右边索引【2】,要插入排序的数据为【23】
左边索引值【0】 小于等于 右边索引值【2】
(左边索引值【0】+右边索引值【2】)/2得到中间索引值【1】
要插入排序的数据【23】大于等于中间值【arr[1]=9】,左边索引值(中间索引值【1】加1)变为【2】
左边索引值【2】 小于等于 右边索引值【2】
(左边索引值【2】+右边索引值【2】)/2得到中间索引值【2】
要插入排序的数据【23】大于等于中间值【arr[2]=10】,左边索引值(中间索引值【2】加1)变为【3】
左边索引值【3】 大于 右边索引值【2】,退出内层循环
要插入的位置【3】和当前位置【3】一致不用移动数据
第【3】轮排序后的结果:[8, 9, 10, 23, 21, 19]
-------------------------------------
第【4】轮排序前的结果:[8, 9, 10, 23, 21, 19]
第【4】轮排序,左边索引【0】,右边索引【3】,要插入排序的数据为【21】
左边索引值【0】 小于等于 右边索引值【3】
(左边索引值【0】+右边索引值【3】)/2得到中间索引值【1】
要插入排序的数据【21】大于等于中间值【arr[1]=9】,左边索引值(中间索引值【1】加1)变为【2】
左边索引值【2】 小于等于 右边索引值【3】
(左边索引值【2】+右边索引值【3】)/2得到中间索引值【2】
要插入排序的数据【21】大于等于中间值【arr[2]=10】,左边索引值(中间索引值【2】加1)变为【3】
左边索引值【3】 小于等于 右边索引值【3】
(左边索引值【3】+右边索引值【3】)/2得到中间索引值【3】
要插入排序的数据【21】小于中间值【arr[3]=23】,右边索引值(中间索引值【3】减1)变为【2】
左边索引值【3】 大于 右边索引值【2】,退出内层循环
数据【arr[3]】到【arr[3]】往后移动,即:
数据【arr[3]】移动到【arr[4]】
要插入排序的数据【21】插入到【arr[3]】的位置
第【4】轮排序后的结果:[8, 9, 10, 21, 23, 19]
-------------------------------------
第【5】轮排序前的结果:[8, 9, 10, 21, 23, 19]
第【5】轮排序,左边索引【0】,右边索引【4】,要插入排序的数据为【19】
左边索引值【0】 小于等于 右边索引值【4】
(左边索引值【0】+右边索引值【4】)/2得到中间索引值【2】
要插入排序的数据【19】大于等于中间值【arr[2]=10】,左边索引值(中间索引值【2】加1)变为【3】
左边索引值【3】 小于等于 右边索引值【4】
(左边索引值【3】+右边索引值【4】)/2得到中间索引值【3】
要插入排序的数据【19】小于中间值【arr[3]=21】,右边索引值(中间索引值【3】减1)变为【2】
左边索引值【3】 大于 右边索引值【2】,退出内层循环
数据【arr[3]】到【arr[4]】往后移动,即:
数据【arr[4]】移动到【arr[5]】
数据【arr[3]】移动到【arr[4]】
要插入排序的数据【19】插入到【arr[3]】的位置
第【5】轮排序后的结果:[8, 9, 10, 19, 21, 23]

  眼睛根据数据走,看完你肯定会懂整个流程的,如果还不懂,可能二分查找算法和 直接插入排序还没完全弄懂。

3.2、日志精简版

public static void binaryInsertSort2(int[] arr) {// 获取数组的长度int len = arr.length;// 遍历数组从索引为1的位置开始,for (int i = 1; i < len; i++) {// 定义左边索引int leftIndex = 0;// 定义右边索引int rightIndex = i - 1;// 定义当前要进行插入排序的数据int insertValue = arr[i];// 只要左边索引小于等于右边的索引就进行遍历while (leftIndex <= rightIndex) {// 获取中间索引值int middleIndex = (leftIndex + rightIndex) / 2;// 判断待插入排序的数据和中间值进行比较if (insertValue >= arr[middleIndex]) {// 修改左边索引leftIndex = middleIndex + 1;} else {// 修改右边索引rightIndex = middleIndex - 1;}}// 左边索引右边的数据 到 要排序的数据之前的数据 都往后移动一位for (int j = i; j > leftIndex; j--) {// arr[j-1]移动到arr[j]arr[j] = arr[j - 1];}// 要插入排序的数据插入到左边索引的位置arr[leftIndex] = insertValue;log.info("第【{}】轮排序后的结果:{}", i, arr);}
}

运行结果:

要排序的数据:[8, 10, 9, 23, 21, 19]
第【1】轮排序后的结果:[8, 10, 9, 23, 21, 19]
第【2】轮排序后的结果:[8, 9, 10, 23, 21, 19]
第【3】轮排序后的结果:[8, 9, 10, 23, 21, 19]
第【4】轮排序后的结果:[8, 9, 10, 21, 23, 19]
第【5】轮排序后的结果:[8, 9, 10, 19, 21, 23]

结语

  二分插入排序是在直接插入排序基础上进行优化的,如果数据列表不是非常的有序的话,理论上二分插入排序 的效率要比 直接插入排序效率要高,尤其是提现在大量的数据进行排序时,但是使用二分插入排序前,先弄懂二分查找算法才会事半功倍。

(六)Java算法:二分插入排序相关推荐

  1. Java算法 -- 二分查找:查找目标元素最左的位置和最右的位置、局部最小值问题求解

    1. 二分查找 二分查找也是一种在数组中查找数据的算法.它只能查找已经排好序的数据.二分查找通过比较数组中间的数据与目标数据的大小,可以得知目标数据是在数组的左边还是右边.因此,比较一次就可以把查找范 ...

  2. java 算法之插入排序

    1.插入排序的思想就是:对于给定的一组记录,初始时假设第一个自成一个有序序列,其余记录为无须序列.接着从第二个开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中,直至最后一个记录插入到有 ...

  3. java二分排序法原理_Java常见排序算法详解—— 二分插入排序

    转载请注明出处: 二分插入排序Binary Insert Sort 概念: 二分(折半)插入排序是一种在直接插入排序算法上进行小改动的排序算法.其与直接排序算法最大的区别在于查找插入位置时使用的是二分 ...

  4. 我的Java开发学习之旅------Java经典排序算法之二分插入排序

    一.折半插入排序(二分插入排序) 将直接插入排序中寻找A[i]的插入位置的方法改为采用折半比较,即可得到折半插入排序算法.在处理A[i]时,A[0]--A[i-1]已经按关键码值排好序.所谓折半比较, ...

  5. 十大经典排序算法之插入排序及其二分优化

    一.插入排序的实现 1.什么是插入排序呢 插入排序的工作方式像许多人排序一手扑克牌.开始时,我们的左手为空并且桌子上的牌面向下.然后,我们每次从桌子上拿走一张牌并将它插入左手中正确的位置.为了找到一张 ...

  6. 插入排序算法 java_排序算法实现-插入排序(Java版本)

    原标题:排序算法实现-插入排序(Java版本) 插入排序(英语:Insertion Sort)是一种简单直观的排序算法.它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到 ...

  7. java 二分查找_计算机入门必备算法——二分查找法

    1.引言 笔者对于计算机的研究一直停滞不前,近期想对一些算法进行复习和进一步的研究,每天都会更新一个新的算法,算法有难有易,层层递进.不希望能学的有多么高深,只希望在一些最基本的算法上有编码的思路,或 ...

  8. 1.1.10 从二分查找BinarySearch开启算法学习之路---《java算法第四版》

    文章目录 0.前言 1.功能 2.示例 有两个名单tinyW.txt和tinyT.txt,将tinyT.txt名单中不在tinyW.txt的数据打印出来 ① 实现原理 ② 实现代码 ③ 性能分析 0. ...

  9. Java常见排序算法之插入排序

    一.概述 本节由小千给大家分享Java常见排序算法之插入排序,之前我们说过排序是算法中的一部分.所以我们学习排序也是算法的入门,为了能让大家感受到排序是算法的一部分,我举个例子证明一下:比如麻将游戏, ...

最新文章

  1. python布尔测试对象_面试题十九期-测试开发面试题之python系列-这个中~
  2. 数组查找———二分(折半)查找法
  3. HTTP over QUIC重命名为“HTTP / 3”协议
  4. javascript中判断对象是否为空几种场景
  5. 解决安装SQL Server 2005开发版时,出现“SQL Server 服务无法启动 ”点击重试或取消的解决方法
  6. python 怎么拷贝一个文件到一个新的文件_Python脚本提取不同文件夹里面的文件到一个新的文件...
  7. USACO Section2.2 Preface Numbering 解题报告 【icedream61】
  8. python3 数据结构_Python3数据结构
  9. [生存志] 第55节 吴公子札巡访中原
  10. 用纯css实现优雅的tab页,纯CSS实现Tab页切换效果的方法
  11. 传统企业如何实现数字化转型
  12. echarts地图api series_ECharts地图绘制和钻取简易接口详解
  13. bugku---game1
  14. Mac上UltraEdit v18.00.0.22 分享
  15. AOJ-AHU-OJ-6 Hero in Maze
  16. linux入门,满足工作中常见小场景。(持续更新)
  17. linux基础unit13-软件安装
  18. Docker 入门到实战 之 安装RocketMQ
  19. 删掉系统服务里边的tomcat7服务
  20. 计算机科学与技术各大学排名,计算机科学与技术学科排行榜(大学名单大全2020版)...

热门文章

  1. latex 制作个人简历,CV
  2. 源代码|大屏可视化系统 数据可视化
  3. 每天和琦琦学点新知识_爬虫篇001
  4. 【100%通过率】华为OD机试真题 Java 实现【最长回文字符串】【2023 Q1 | 100分】
  5. 用html,css,js来绘制中国地图
  6. 浪潮nf5280m5安装linux网卡,浪潮英信服务器NF5280M5
  7. 下载的小说是php,冷迪小说全自动采集程序php版(原名:冷迪小说小偷) v2.0
  8. 软件开发工作会在35-40岁走入死胡同吗?
  9. android 填充,Android Drawable部分填充
  10. 转行程序员?三思而后行