首页 > 编程语言 > 详细

v8--sort 方法 源码 的 插入排序法

时间:2019-11-15 01:21:24      阅读:113      评论:0      收藏:0      [点我收藏+]

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。

插入排序法是将待比较的数值与它的前一个数值进行比较,所以外层循环是从第二个数值开始的。

开始循环数组,索引初值为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,把索引中值mid + 1赋值给min。即 min = mid + 1。继续循环

如果计算值大于0,把索引中值mid 赋值给max。继续循环

技术分享图片

 该循环一直到min = max后结束。取得min值。

接着以当前已循环次数i作为初始值,另存副本j = i,以j > min作为判断条件。

依次把前一索引值赋值给当前索引值,如 a[3] = a[2],a[2] = a[1] 

最后把哨兵赋值给插入点。即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;
      }
      /**
       * 已循环的数组是有序的数组,索引中值对应的值与哨兵比较
       * 小于则将mid赋值给min,继续取min与max值的中值。然后比较该中值对应的值与哨兵的大小
       * 大于则将中值赋值给max值,在取min与新max的中值,然后比较该中值对应的值与哨兵的大小
       * 循环往复,直到min = max,退出该循环,找到插入点
      */
      if (order < 0) {
        min = mid + 1
      } else {
        max = mid
      }
    }

    /**
     * 插入操作循环,从已循环数组的末尾开始,依次把上一个索引值赋给当前索引值
     * 如: a[3] = a[2] a[2] = a[1],一直到插值位置min。
     * 循环结束后,把哨兵赋值给arr[min]
     * 
    */
    for (let j = i; j > min; j--) {
      arr[j] = arr[j - 1]
    }
    arr[min] = key
  }
}

调试:

技术分享图片

 

 

 

 

 

v8--sort 方法 源码 的 插入排序法

原文:https://www.cnblogs.com/caimuguodexiaohongmao/p/11863648.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!