zoukankan      html  css  js  c++  java
  • 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 } }

    调试:

  • 相关阅读:
    JavaScript中数组的迭代方法:forEach、map、filter、reduce、every、some、for in、for of
    node-express项目的搭建并通过mongoose操作MongoDB实现增删改查分页排序(四)
    Centos下MongoDB数据库的安装以及配置开机自启动(三)
    MongoDB在MacOS上的客户端Robo 3T 的简单使用(二)
    MacOS系统下简单安装以及配置MongoDB数据库(一)
    修改echarts环形图的牵引线及文字位置
    vue 父子组件传值以及方法调用,平行组件之间传值以及方法调用大全
    css加载会造成阻塞吗?
    vue 之 Virtual Dom
    async/await学习笔记
  • 原文地址:https://www.cnblogs.com/caimuguodexiaohongmao/p/11863648.html
Copyright © 2011-2022 走看看