>> 插入排序


本编重点在最后: 为什么二分插入left总是指向待插入的位置?

插入排序的思路: 给定一个数组,将数组划分为,已排序和未排序两部分,默认第一个元素已排序,然后一次遍历未排序数列,找到每个元素在已排序数列中的位置,移动元素,并插入。
平均时间复杂度: O(n^2)
最好情况: O(n)
最坏情况: O(n^2)
空间复杂度: O(1)
稳定性: 稳定 排序前相等的两个数,排序后位置不变


:)直接插入排序

代码如下:

import java.util.*;/**   插入排序---直接插入排序* */
public class InsertSort{private static Random rand = new Random();public static void insertSort(int[] value,int length){int temp;for(int i=1;i<length;i++){temp=value[i];int j=i-1;while(j>=0&&value[j]>temp){value[j+1]=value[j];j--;}//到这里的时候,要么是j小于0,要么value[j]小于了temp,所以直接//将value[j+1]z赋值为temp。value[j+1]=temp;}}public static void main(String[] args){int[] s = new int[100];for(int i = 0;i<s.length;i++){s[i]=Math.abs(rand.nextInt()%1000);}System.out.println(Arrays.toString(s));System.out.println("排序中...");insertSort(s,s.length);System.out.println(Arrays.toString(s));}
}
在寻找插入位置的过程中,如果遇到大于待插入的数,就直接向后移动,直到遇到小于它的数,这时候 j 指向的数的值就是第一个小于它的数的下标, 所以最后使用了 value[ j + 1 ]=temp。

:)二分插入排序

代码如下:

import java.util.*;
/** 插入排序----二分法插入排序* */
public class InsertSort2{public static void insertSort2(int[] value,int length){for(int i=1;i<length;i++){int left = 0;int right = i-1;int temp = value[i];//这里必须为<=,因为,如果没有等于,那么i=1的时候,循环就已经结束了。//循环结束之后,left是要插入的位置,right是要插入位置的前一个位置。//这所以会出现,left是要插入的位置,right是要插入的前一个位置,是因为,left代表的待插入数字中的高位,right是低位。while(left<=right){int mid = (left+right)/2;if(value[mid]>temp)right=mid-1;else left=mid+1;}//找打下标之后,将数字往后移,并且这个循环必须从最后一个数开始移动,避免覆盖掉前面的数字。for(int j=i-1;j>=left;j--){value[j+1]=value[j];}//将值插入相应的位置。value[left]=temp;}}public static void main(String[] args){Random rand = new Random();int[] s = new int[100];for(int i=0;i<s.length;i++){s[i]=Math.abs(rand.nextInt()%100);}System.out.println(Arrays.toString(s));System.out.println("排序中...");insertSort2(s,s.length);System.out.println(Arrays.toString(s));}
}

二分插入排序与直接插入排序的区别就在: 如何寻找待插入位置。

重点在为什么while循环之后left是待插入的位置

  • 根据我们在while循环体中的写法,我们可以保证left之前的数一定小于待插入的数,而right之后的数一定大于待插入的数。
  • 并且,不管什么情况,最后,left和right都会指向同一个下标
  • 以上两点连接起来就可以解决问题当最后left和right指向同一个下标,那么它们共同指向的这个数,与待插元素的大小就决定了,插入的位置。如果待插元素大于或等于这个数,那么就应该插入到这个数前面,这时根据代码可知left=mid+1;如果小于这个数,就应该插入到这个数后面,这时right=mid-1。
    但是不管如何,最后left和right一定满足这样一个关系:
    left = right+1
    所以,如果按照大小顺序排列的话,right将在left左边,这与为它们的命名产生矛盾。
    这时,再根据第一点来分析,left左边的数一定小于left指向的这个数,right右边的数一定大于这个数。但最后的left和right的排序却是
    right left
    我们将目光聚焦到left,分析可以,left左边的数一定小于待插元素,而此时,right在它左边,right右边的数一定大于待插元素,那么可以得出:
    left最后所指向的数,是待插位置右边那个数,如:7 插入 3 ,9之间,那么left就指向9。
    同理可以得出:
    right最后所指向的数,是待插位置左边那个数,如:7 插入 3 ,9之间,那么right就指向3。
    这就是为什么left所指向的是待插入的位置,因为最后大于待插入的数才会向后移动。

深入理解插入排序(why二分插入排序中left就是待插入位置)相关推荐

  1. python插入排序_python简单的实现插入排序和二分插入排序

    零:环境 Python 3.6.5 JetBrains PyCharm 2018.1.4 x64 一:正常的插入排序 插入排序如字面意思,是将数据一个一个的插入到列表里以形成有序数列 插入排序的前提是 ...

  2. 堆排序、二分插入排序(C++代码)

    一.堆排序 要弄明白堆排序,我们首先要明白什么叫堆,堆可以理解为把一个完全二叉树放到一个数组里.也就是说这个完全二叉树按照层数从根节点那层开始被削成一层一层的往数组里面依次摆放. 我们不难得到这个关系 ...

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

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

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

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

  5. (六)Java算法:二分插入排序

    目录 一.前言 二.maven依赖 三.实现 3.1.详解版 3.2.日志精简版 结语 一.前言   插入排序常见的有两种:直接插入排序 和 二分插入排序,我们上一篇算法已经讲过了直接插入排序,现在我 ...

  6. 向Array中添加二分插入排序

    二分插入排序思路 先在有序区通过二分查找的方法找到移动元素的起始位置,然后通过这个起始位置将后面所有的元素后移. 二分插入排序实现 Function.prototype.method = functi ...

  7. 插入排序之——二分(折半)插入排序(c/c++)

    相比较直接插入排序,二分插入的优势在于:对待排序数所应该插入的位置的计算是通过二分法来寻找的,这种二分查找的时间复杂度为o(logn):而直接插入是依次寻找位置的,时间复杂度可看作o(n). 故二分插 ...

  8. JavaSE(二十四)——冒泡排序、选择排序、直接插入排序以及二分查找

    文章目录 1. 冒泡排序 2. 选择排序 3. 直接插入排序 4. 二分查找 1. 冒泡排序 原理:数组元素两两比较,大的往后放,经过一轮比较后,最大元素在最后面,如此往复. 举例说明: 代码: // ...

  9. C语言排序方法-----二分插入排序

    由于在直接插入排序过程中,待插入数据左边的序列总是有序的,针对有序序列,就可以用二分法去插入数据了,也就是二分入排序法.适用于数据量比较大的情况. 二分插入排序的算法思想是: (1)计算 0 ~ i- ...

最新文章

  1. VC四种程序启动画面的制作方法
  2. Gradle 依赖项管理
  3. 如何卸载MySQL8.0.11_win10安装mysql8.0.11卸载5.7
  4. Leedcode6-binary-tree-preorder-traversal
  5. 拼多多市值超1600亿美元 成中国第四大互联网公司
  6. [Misc]IE浏览器真正全屏幕操作技巧
  7. MessageDigest 类的用法
  8. andorid安卓优秀博文源码推荐集锦
  9. 说一说协议生成器 - Ricequant米筐量化
  10. Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
  11. java微博模拟登陆_java+selenium模拟登陆新浪微博demo
  12. 了解TrustZone,读了这篇就够了
  13. 已有虚拟磁盘多个vmdk文件导入虚拟机
  14. C语言—字符串函数和内存函数
  15. Python + PIL 处理支付宝AR红包
  16. 对象上下文语义分割:OCR论文笔记(Object-Contextual Representations for Semantic Segmentation )
  17. 中国园区经济行业“十四五“规划与前景深度研究报告2021年版
  18. 真正的端到端超像素网络——Superpixel Segmentation with Fully Convolutional Networks(CVPR2020)
  19. Excel2016 无法粘贴图片
  20. 【全国计算机等级考试二级教程——C语言程序设计(2021年版)编程题答案-第7章】

热门文章

  1. 怎样在PPT中抠图?这样操作30秒搞定!
  2. TreeSet,海康威视java校招面试题
  3. openwrt wifi 出现missing ACKs和deauthenticated due to inactivity 频繁掉线问题解决方案
  4. python微信小程序 java电子书阅读器系统uniapp
  5. 攻防世界--Confusion2
  6. python tkinter button 透明图片_如何使Tkinter支持PNG透明?
  7. POS消费小票(签购单)上的“秘密”
  8. 系统性能优化的十大策略(强烈推荐,建议收藏)
  9. e.hash oldCap == 0 详细解读
  10. Java实现 LeetCode 345 反转字符串中的元音字母