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) 插入排序法的更多相关文章

  1. v8--sort 方法 源码 (2) 快速排序法

    v8 sort方法部分关于快速排序法的源码: function QuickSort(a, from, to) { // Insertion sort is faster for short array ...

  2. erlang下lists模块sort(排序)方法源码解析(二)

    上接erlang下lists模块sort(排序)方法源码解析(一),到目前为止,list列表已经被分割成N个列表,而且每个列表的元素是有序的(从大到小) 下面我们重点来看看mergel和rmergel ...

  3. erlang下lists模块sort(排序)方法源码解析(一)

    排序算法一直是各种语言最简单也是最复杂的算法,例如十大经典排序算法(动图演示)里面讲的那样 第一次看lists的sort方法的时候,蒙了,几百行的代码,我心想要这么复杂么(因为C语言的冒泡排序我记得不 ...

  4. Java split方法源码分析

    Java split方法源码分析 public String[] split(CharSequence input [, int limit]) { int index = 0; // 指针 bool ...

  5. getOrCreateEnvironment()方法源码探究

    该方法目的是创建一个环境对象,并且根据环境类型,自动判断是创建web环境对象,还是标准非web环境对象. 首先该方法源于prepareEnvironment准备环境: 然后进入该方法源码: 可以发现: ...

  6. TreeSet集合的add()方法源码解析(01.Integer自然排序)

    >TreeSet集合使用实例 >TreeSet集合的红黑树 存储与取出(图) >TreeSet的add()方法源码     TreeSet集合使用实例 package cn.itca ...

  7. invalidate和requestLayout方法源码分析

    invalidate方法源码分析 在之前分析View的绘制流程中,最后都有调用一个叫invalidate的方法,这个方法是啥玩意?我们来看一下View类中invalidate系列方法的源码(ViewG ...

  8. Linq分组操作之GroupBy,GroupJoin扩展方法源码分析

    Linq分组操作之GroupBy,GroupJoin扩展方法源码分析 一. GroupBy 解释: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值. 查询表达式: var ...

  9. Java线程状态、线程start方法源码、多线程、Java线程池、如何停止一个线程

    下面将依次介绍: 1. 线程状态.Java线程状态和线程池状态 2. start方法源码 3. 什么是线程池? 4. 线程池的工作原理和使用线程池的好处 5. ThreadPoolExecutor中的 ...

随机推荐

  1. crc64

    oss2\models.py class PartInfo(object):     """表示分片信息的文件. 该文件既用于 :func:`list_parts < ...

  2. Selenium+Java完整框架搭建(2019完整版)

    一.WebDriver框架开发实战 1.框架的思想 (1)什么是框架? 框架是可以被应用开发者定制的应用骨架 (2)为什么要写框架? 提高脚本可维护性 提高编写脚本的速度 提高脚本可阅读性 (3)框架 ...

  3. (转)react 项目构建

    原文:https://segmentfault.com/a/1190000016342792 写在前面 每次构建react项目的时候都会配置一大堆东西,时间久了就会忘记怎么配置.为了方便自己记忆也为了 ...

  4. Golang常见小细节总结(1)

    本系列不定期更新,用于记录平常开发过程中出现的一些小问题 Array 类型的值作为函数参数    可以理解slice是对array的一个视图,底层还是array所以会被修改 通过map的ok来确 ...

  5. postman 用环境变量Environment实现多服务器版本

    现存问题 在测试API期间,往往存在多种环境,对应IP地址(或域名也不同) 比如: Prod: http://116.62.25.57/ucows 用于开发完成发布到生产环境 Dev: http:// ...

  6. redis-cli中文乱码

    在开发过程中,需要验证redis缓存中的数据,发现redis存储的中文全是乱码,因为默认情况下redis不转义中文.如果在平常开发中想要看到中文内容,可以在使用redis-cli 命令登陆redis服 ...

  7. 《深入理解Linux内核》 读书笔记

    深入理解Linux内核 读书笔记 一.概论 操作系统基本概念 多用户系统 允许多个用户登录系统,不同用户之间的有私有的空间 用户和组 每个用于属于一个组,组的权限和其他人的权限,和拥有者的权限不一样. ...

  8. YII2框架集成go!aop

    AOP实践:YII2框架本身拥有一个功能,叫做行为.它可以动态的为当前的类附加额外的功能,但这种功能在代码层级结构是静态的,有侵入性的. 下面以YII2框架集成go!aop库为例,介绍在YII2中如何 ...

  9. massif 图例

    19.63^ ### | # | # :: | # : ::: | :::::::::# : : :: | : # : : : :: | : # : : : : ::: | : # : : : : : ...

  10. dedecms原理及使用

    dedecms原理 简单使用 现在老板要求你做一个文章管理系统,栏目(类别)包括(武侠.爱情.音乐...) ,每个栏目(类别)有对应的文章,文章已经给你准备好了,请你在30分钟搞定该网站,怎么样? 步 ...