v8--sort 方法 源码 (1) 插入排序法
v8--sort方法源码中对于长度较短的数组使用的是插入排序法。
部分源码:
- function InsertionSort(a, from, to) {
- for (var i = from + 1; i < to; i++) {
- var element = a[i];
- // Pre-convert the element to a string for comparison if we know
- // it will happen on each compare anyway.
- var key =
- (custom_compare || %_IsSmi(element)) ? element : ToString(element);
- // place element in a[from..i[
- // binary search
- var min = from;
- var max = i;
- // The search interval is a[min..max[
- while (min < max) {
- var mid = min + ((max - min) >> 1);
- var order = Compare(a[mid], key);
- if (order == 0) {
- min = max = mid;
- break;
- }
- if (order < 0) {
- min = mid + 1;
- } else {
- max = mid;
- }
- }
- // place element at position min==max.
- for (var j = i; j > min; j--) {
- a[j] = a[j - 1];
- }
- a[min] = element;
- }
- }
源码的理解:
参数:a--数组。form起点索引即0。to终点索引。
源码对数组长度进行了计算,如值为undefined会被移至数组末尾并且长度会减去。
通常如果是正经的数组to就是a.length。
需要注意的是,以上都仅仅是在初始数组长度小于22时的情况。
此插入排序法是将待比较的数值与外层循环当前值对比,外层循环是从第二个数值开始的。
开始循环数组,索引初值为1。创建一个哨兵,保存当前循环索引对应的值 。
即key = a[i],该值需要插入到已循环数组的某个位置。
创建max,记录已循环次数。即 max = i
创建min,记录插入位置。初值是0 即 min = 0
内层循环1,目的找出插入的位置。循环条件 min < max
该循环内,创建mid 保存min和max的中值。然后计算该中值对应的数组值与哨兵的大小。即compare(arr[mid], key)
需要注意的是,mid min max 都是数组的索引。
如果计算结果为0,即说明索引中值对应值与哨兵值相等。
那么插入位置就是这个点。把mid赋值给min,取得插入点。退出该循环
如果计算值小于0。比如已经排序好的有序数组个数是15。索引中值是7。a[7]与key(即a[16])比较小于0。即key大于a[7]
说明key应该要插入到a[7]后面。则插入点最起码应该在索引7后面。故令min = 7 + 1;然后继续循环找出最合适的位置。
如果计算值大于0,还是上面那个例子。a[7]与key(即a[16])比较大于0。即key小于a[7]
说明key应该要插入到a[7]前面。则插入点最起码应该在索引7前面。故令max = mid;然后继续循环找出最合适的位置。
该循环一直到min = max后结束。取得min值。
接着以当前已循环次数i作为初始值,另存副本j = i,以j > min作为判断条件。
依次把前一索引值赋值给当前索引值,如 a[16] = a[15],a[15] = a[14] 等等等
最后把哨兵赋值给插入点。即a[min] = key
至于排序是为升降序。则由比较函数的判断
如最简单的比较函数:(x, y) => return x - y
返回参数1 减去 参数2 的值。即索引中值对应值减去哨兵
索引中值对应值小于哨兵,则计算结果小于0。按照上述逻辑,把mid+1赋值给min。则插入点在该索引后面,故为升序
索引中值对应值大于哨兵,则计算结果大于0。按照上述逻辑,把mid赋值给max。则插入点在该索引前面,还是升序
图解
代码:
- function insertSort(arr) {
- for(let i= 1; i < arr.length; i++) {
- let key = arr[i] // 哨兵,保存当前循环索引对应的值,需要插入到已循环数组中
- let min = 0 // 插入位置
- let max = i // 已循环次数
- // 遍历已循环的数组,找寻插入位置
- while(min < max) {
- // 中值 >>有符号右移 类似于 Math.floor(int/2) int是正整数
- let mid = min + ((max - min) >>1)
- // 比较函数,传入索引中值对应的值和哨兵
- const order = compare(a[mid], key)
- // 如果等于0
- if (order === 0) {
- // 把mid赋值给min。作为插入位置,退出循环
- min = max = mid
- break;
- }
- // 小于0。插入位置在该索引中值后面
- if (order < 0) {
- min = mid + 1
- } else { // 大于0。插入位置在该索引中值前面
- max = mid
- }
- }
- for (let j = i; j > min; j--) {
- arr[j] = arr[j - 1]
- }
// 插入- arr[min] = key
- }
- }
调试:
v8--sort 方法 源码 (1) 插入排序法的更多相关文章
- v8--sort 方法 源码 (2) 快速排序法
v8 sort方法部分关于快速排序法的源码: function QuickSort(a, from, to) { // Insertion sort is faster for short array ...
- erlang下lists模块sort(排序)方法源码解析(二)
上接erlang下lists模块sort(排序)方法源码解析(一),到目前为止,list列表已经被分割成N个列表,而且每个列表的元素是有序的(从大到小) 下面我们重点来看看mergel和rmergel ...
- erlang下lists模块sort(排序)方法源码解析(一)
排序算法一直是各种语言最简单也是最复杂的算法,例如十大经典排序算法(动图演示)里面讲的那样 第一次看lists的sort方法的时候,蒙了,几百行的代码,我心想要这么复杂么(因为C语言的冒泡排序我记得不 ...
- Java split方法源码分析
Java split方法源码分析 public String[] split(CharSequence input [, int limit]) { int index = 0; // 指针 bool ...
- getOrCreateEnvironment()方法源码探究
该方法目的是创建一个环境对象,并且根据环境类型,自动判断是创建web环境对象,还是标准非web环境对象. 首先该方法源于prepareEnvironment准备环境: 然后进入该方法源码: 可以发现: ...
- TreeSet集合的add()方法源码解析(01.Integer自然排序)
>TreeSet集合使用实例 >TreeSet集合的红黑树 存储与取出(图) >TreeSet的add()方法源码 TreeSet集合使用实例 package cn.itca ...
- invalidate和requestLayout方法源码分析
invalidate方法源码分析 在之前分析View的绘制流程中,最后都有调用一个叫invalidate的方法,这个方法是啥玩意?我们来看一下View类中invalidate系列方法的源码(ViewG ...
- Linq分组操作之GroupBy,GroupJoin扩展方法源码分析
Linq分组操作之GroupBy,GroupJoin扩展方法源码分析 一. GroupBy 解释: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值. 查询表达式: var ...
- Java线程状态、线程start方法源码、多线程、Java线程池、如何停止一个线程
下面将依次介绍: 1. 线程状态.Java线程状态和线程池状态 2. start方法源码 3. 什么是线程池? 4. 线程池的工作原理和使用线程池的好处 5. ThreadPoolExecutor中的 ...
随机推荐
- ANR日志分析
2018年06月27日 16:28:13 Hello__code 阅读数 3427更多 分类专栏: bug记录 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出 ...
- pip安装daemon模块
E:\> pip install python-daemon Collecting python-daemon Downloading https://files.pythonhosted.or ...
- 接口项目servlet的一种处理方式,将异常返回给调用者【我】
接口项目servlet的一种处理方式,其他层有异常全部网上抛,抛到servlet层,将异常返回给调用者: Servlet层: private void processRequest(HttpServl ...
- HDFS java API TROUBLESHOOTING
官方文档:https://hadoop.apache.org/docs/r2.9.2/hadoop-project-dist/hadoop-common/SingleCluster.html 配置免密 ...
- OKEx交易所交易记录日期时间转毫秒级时间戳
本文介绍如何将OKEx交易所成交记录数据中的日期时间转毫秒级时间戳. 作者:比特量化 1. OKEx交易记录格式 [ { "time":"2019-09-14T10:29 ...
- Xshell连接SqlPlus无法使用退格、删除键
问题:在使用xshell连接CentOS7,进入SQLPLUS进行命令操作时,如果输错了信息,无法进行退格键删除(显示“^H”),同样按删除键,显示“^[[3~”. 解决:网上查找了相关资料,可以通过 ...
- OpenVAS开源风险评估系统部署方案
OpenVAS,即开放式漏洞评估系统,是一个用于评估目标漏洞的杰出框架.功能十分强大,最重要的是,它是“开源”的——就是免费的意思啦- 它与著名的Nessus“本是同根生”,在Nessus商业化之后仍 ...
- 【插件】【idea】的Mybatis Plugin插件方便mapper接口方法和mapper XML文件之间来回切换
效果 安装 这是2019.2版本的,旧版的有点不一样
- 1 RAID技术入门
序 RAID一页通整理所有RAID技术.原理并配合相应RAID图解,给所有存储新人提供一个迅速学习.理解RAID技术的网上资源库,本文将持续更新,欢迎大家补充及投稿.中国存储网一如既往为广大存储界 ...
- window安装mysql8.0解决大部分客户端无法连接问题登陆问题
https://blog.csdn.net/u013308810/article/details/80114021