JavaScript 的 Array.prototype.sort 排序算法(含排序算法链接) - Go语言中文社区

JavaScript 的 Array.prototype.sort 排序算法(含排序算法链接)


深入浅出 JavaScript 的 Array.prototype.sort 排序算法

1、找出 Array.prototype.sort 使用的什么排序算法

2、用一种直观的方式展示 Array.prototype.sort 的时间复杂度,看看它有多快?

Array.prototype.sort 各浏览器的算法实现

ECMAScript 5.1
ECMAScript 6.0
ECMAScript 草案
看完上面三个规范中 Array.prototype.sort 部分,我们会发现 ECMAScript 不同版本规范对 Array.prototype.sort 的定义中没有要求用什么样的排序方式实现 sort() 方法,也没有要求是否要采用稳定排序算法(下文会解释什么是稳定排序算法)。
在这里插入图片描述
Google Chrome算法源码地址
Mozilla Firefox算法源码地址
Safari算法源码地址
Microsoft Edge 和 IE(9+)算法源码地址

源码分析

V8 引擎的一段注释

// In-place QuickSort algorithm.
// For short (length <= 10) arrays, insertion sort is used for efficiency.

Google Chrome 对 sort 做了特殊处理,对于长度 <= 10 的数组使用的是插入排序(稳定排序算法) ,>10 的数组使用的是快速排序。快速排序是不稳定的排序算法。

但是很明显比我们常见的快速排序要复杂得多,不过核心算法还是快速排序。算法复杂的原因在于 v8 出于性能考虑进行了很多优化。

再看 safari Nitro 引擎的一段代码:

if (typeof comparator == "function")
  comparatorSort(array, length, comparator);
else if (comparator === null || comparator === @undefined)
  stringSort(array, length);

  省略....

function stringSort(array, length)
{
  var valueCount = compact(array, length);

  var strings = @newArrayWithSize(valueCount);
  for (var i = 0; i < valueCount; ++i)
      strings[i] = { string: @toString(array[i]), value: array[i] };

  bucketSort(array, 0, strings, 0);
}

  省略....

function comparatorSort(array, length, comparator)
{
  var valueCount = compact(array, length);
  mergeSort(array, valueCount, comparator);
}

默认使用的桶排序,如果 sort 传入的自定义函数作为参数,就是用归并排序(稳定排序算法)

Firefox 源码就不贴了,上面的表格有源码地址,使用的稳定排序算法 — 归并算法。
Microsoft Edge 和 IE(9+) 使用的不稳定排序算法 - 快速排序。
但是 IE(6、7、8)使用的稳定算法。
在这里插入图片描述
算法时间复杂度

在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,
进而分析T(n)随着n的变化情况并确定T(n)的数量级。
算法的时间复杂度,也就是算法的时间度量,记作:T(n)=O(f(n))。
它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,
称作算法的时间复杂度,简称为时间复杂度。
其中f(n)是问题规模n的某个函数。
常用的时间复杂度所耗费的时间从小到大依次是

O(1) < O(logn) < O(n) < O(nlogn) < O(n²) < O(n³) < O(2^n) < O(n!) < O(n^n)

算法的时间复杂度与运行时间有一些常见的比例关系在这里插入图片描述
维基百科关于算法稳定性的解释
当相等的元素是无法分辨的,比如像是整数,稳定性并不是一个问题。然而,假设以下的数对将要以他们的第一个数字来排序。

(4, 1) (3, 1) (3, 7)5, 6

在这个状况下,有可能产生两种不同的结果,一个是让相等键值的纪录维持相对的次序,而另外一个则没有:

(3, 1)  (3, 7)  (4, 1)  (5, 6)  (维持次序)
(3, 7)  (3, 1)  (4, 1)  (5, 6) (次序被改变)

想看自己浏览器排序算法的稳定性?

各种排序算法实现有多快?

我们先通过这个在线网站大体测试一下

对一个有 10000 个元素的数组,快速排序 > 归并排序 >>> 插入排序
而且插入排序大于 1s 了。

对于一个只有 10 个元素的数组,插入排序 > 快速排序
这也说明了为什么 chrome 在小于等于 10 个元素的小数组使用插入排序的原因了。

浏览器的实现不同有什么影响

排序算法不稳定有什么影响

举个例子:

某市的机动车牌照拍卖系统,最终中标的规则为:

1、按价格进行倒排序;

2、相同价格则按照竞标顺位(即价格提交时间)进行正排序。

排序若是在前端进行,那么采用快速排序的浏览器中显示的中标者很可能是不符合预期的。

解决办法
Array.prototype.sort 在不同浏览器中的差异和解决办法

大体的思路就是,自己写一个稳定的排序函数,以保持各浏览器的一致性。

扩展阅读

1、快速排序(Quicksort)的Javascript实现
2、JS中可能用得到的全部的排序算法
3、7 种常用的排序算法-可视化
4、深入了解javascript的sort方法
5、JavaScript 排序算法汇总

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_43936704/article/details/104340019
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-05-22 14:02:58
  • 阅读 ( 2076 )
  • 分类:算法

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢