16、Array.sort()方法和实现机制

每个浏览器中对排序方法的实现都不太一样

  • Google的Chrome浏览器的JavaScript引擎是:V8——数组长度小于等于 10 的用插入排序InsertionSort,比10大的数组则使用快速排序 QuickSort
  • Mozilla的Firefox浏览器的JavaScript引擎是:SpiderMonkey——归并排序源码
  • Safari浏览器的JavaScript引擎是:Nitro(JavaScriptCore )——桶排序和归并排序
  • IE浏览器的JavaScript引擎是:Chakra——使用快排

16.1 插入排序

动图演示
在这里插入图片描述
基本思想

从左往右遍历数组,每次将遍历的项插入到前面的已经排序好的有序数组中,通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

算法步骤

  1. 默认从 i = 1 开始判断,这样 preIndex 自然是内部循环的游标;
  2. current 保存 arr[i],通过循环来确定 current 的最终位置;
  3. 每个内循环开始的时候,arr[i] === current === arr[preIndex + 1],所以在内循环首次时 arr[preIndex + 1] = arr[preIndex] 的时候不必担心 arr[i] 的值丢失;
  4. 总体思路是,需要排位的元素先额外缓存起来,然后套用内循环,使得需要调整的元素赋值给它后面的一个位置上,形成依次挪位,最后因为内循环在判断条件不生效的时候停止意味着找到了需要排位的元素的正确位置,然后赋值上去,完成排序。

代码实现

function Insertion(arr) {
  let len = arr.length;
  let preIndex, current;
  for (let i = 1; i < len; i++) {
    preIndex = i - 1;
    current = arr[i];
    while (preIndex >= 0 && current < arr[preIndex]) {
      arr[preIndex + 1] = arr[preIndex];
      preIndex--;
    }
    arr[preIndex + 1] = current;
  }
  return arr;
}

var arr = [3, 5, 7, 1, 9];
console.log(Insertion(arr))

16.2 快速排序

图片演示
在这里插入图片描述

基本思想

  • 在数据集之中,选择一个元素作为"基准"(pivot)。
  • 所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。
  • 对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。

算法步骤

  1. 定义一个quickSort函数
  2. 检查数组的元素个数,如果小于等于1,就返回。
  3. 选择"基准"(pivot),并将其与原数组分离,再定义两个空数组,用来存放一左一右的两个子集。
  4. 开始遍历数组,小于"基准"的元素放入左边的子集,大于基准的元素放入右边的子集。
  5. 递归重复

代码实现

var quickSort = function (arr) {
  if (arr.length <= 1) { return arr; }
  // 获取基准值得索引
  let pivotIndex = Math.floor(arr.length / 2);
  // 获得索引值
  let pivot = arr.splice(pivotIndex, 1)[0];
  // 定义左右两个空数组
  let left = [];
  let right = [];
  // 分组
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] < pivot) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }
  // 递归
  return quickSort(left).concat([pivot], quickSort(right));
};

// test
console.log(quickSort([1,23,42,5,2,51,2]))

优化后的代码实现

function quickSort(arr) {
  return quick(arr, 0, arr.length - 1)
}

function quick(arr, left, right) {
  let index
  if (arr.length > 1) {
    index = partition(arr, left, right)
    if (left < index - 1) {
      quick(arr, left, index - 1)
    }
    if (index < right) {
      quick(arr, index, right)
    }
  }
  return arr
}

function partition(arr, left, right) {
  const pivot = arr[Math.floor((right + left) / 2)]
  let i = left
  let j = right

  while (i <= j) {
    while (arr[i] < pivot) {
      i++
    }
    while (arr[j] > pivot) {
      j--
    }
    if (i <= j) {
      let temp = arr[i]
      arr[i] = arr[j]
      arr[j] = temp
      i++
      j--
    }
  }
  return i
}

console.log(quickSort([1, 5, 34,3,65,3,23,4,1]))
参考文章

Array.sort 算法原理(插入排序\快速排序in-place实现)
js算法-快速排序(Quicksort)
算法 3:最常用的排序——快速排序

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值