本机JavaScript排序执行速度比实现的mergesort和quicksort慢

本机JavaScript排序执行速度比实现的mergesort和quicksort慢,javascript,node.js,algorithm,performance,sorting,Javascript,Node.js,Algorithm,Performance,Sorting,我实现了一个mergesort和一个quicksort,将它们与本机JavaScript排序进行比较。对于快速排序,我尝试使用以下算法:。这两种算法都使用尽可能少的内存,对于合并排序,为每次递归调用传递一个辅助数组(以避免开销),对于快速排序,起始位置和结束位置。我正在使用排序来管理NodeJs应用程序中的大量数据 下面是mergesort、quicksort和原生JavaScript排序,您可以测试性能 问题是:为什么本机JavaScript执行速度较慢 就我而言: 铬-合并排序:测量值:19

我实现了一个mergesort和一个quicksort,将它们与本机JavaScript排序进行比较。对于快速排序,我尝试使用以下算法:。这两种算法都使用尽可能少的内存,对于合并排序,为每次递归调用传递一个辅助数组(以避免开销),对于快速排序,起始位置和结束位置。我正在使用排序来管理NodeJs应用程序中的大量数据

下面是mergesort、quicksort和原生JavaScript排序,您可以测试性能

问题是:为什么本机JavaScript执行速度较慢

就我而言:

铬-合并排序:测量值:1997.920ms;快速排序:测量值:1755.740ms;本机:测量值:4988.105ms
节点:合并排序:度量:2233.413ms;快速排序:测量值:1876.055ms;本机:测量值:6317.118ms

合并排序
var length=10000000;//千万,;
var-arr=[];
for(设i=length;i>0;i--){
//随机阵列
arr.push(parseInt(Math.random()*100000000));
}
var mergeSort=函数(数组){
功能合并(arr、aux、lo、mid、hi){
用于(var k=lo;k hi){
arr[k]=aux[i++];
}else if(aux[i]如果(hi那么为什么本机排序速度较慢?请查看中的代码

问题似乎是GetThirdIndex()。当分区大小>1000时调用它,我假设它用于防止快速排序最坏情况下的性能,但开销很大,因为它会创建对的内部数组并对其进行排序,而对这些对的排序可能会导致对GetThirdIndex()的进一步递归调用。这与与对原始数组进行分区以及对内部数组对进行分区相关的递归调用相结合

因为这些示例的测试数据是随机数据,所以Relu的快速排序不需要像GetThirdIndex()这样的东西。还需要检查数组中的“洞”,但我认为这并不重要

GetThirdIndex()的另一种替代方法是使用中间值的就地中间值:

合并排序比快速排序快,这些方法用于防止出现最坏情况,但它需要一个与原始数组大小相同或一半的辅助数组

Introsort是quicksort和heapsort的混合体,如果递归级别太深,则可以切换到heapsort:

下面的第二个合并排序示例使用了一个比较函数来进行公平比较。它比本机版本快得多。对于Chrome来说,比较函数对总时间的影响不大。对于Firefox来说,比较函数的作用更大。对于Firefox来说,本机版本由于内存不足而失败是的,所以我无法比较

这些是自上而下的合并排序的更快版本,原始海报对此“好奇”,使用相互递归函数避免复制和稍微优化的merge()(每个比较有两个条件)

Firefox的结果(时间略有不同)

使用铬的结果(时间略有不同)

合并排序

var length=10000000;//一千万;
var-arr=[];
for(设i=length;i>0;i--){
//随机阵列
arr.push(parseInt(Math.random()*100000000));
}
var mergeSort=函数(数组){
功能合并(arr、aux、lo、mid、hi){
VarI=lo;
var j=mid+1;
var k=lo;
while(true){
if(arr[i]mid){
做
aux[k++]=arr[j++];
while(j-hi){
做
aux[k++]=arr[i++];

虽然(我按照你写它们的顺序告诉你,考虑到我的电脑和随机性,第一个是最慢的第二个是最快的:)是的,快速排序执行得最快。那么原生js在你的电脑上比合并排序执行得更好?很有趣。我在Firefox和Edge中查看了这些。在Firefox中,它们三者之间没有太大的差异,尽管原生排序仍然是最慢的。在Edge中,第一个排序从未完成,或者可能我放弃得太快。但它似乎从未停止过r finish。最后两个在Edge中完成。如果您将comparator作为参数传递到自定义实现中会怎么样?这两个自定义实现具有硬编码顺序,而本机是通用的。很可能与vanilla sort灵活且无法利用本机比较op这一事实有关如果您重新编写mergeSort和quickSort以使用compareNumbers而不是
,或者
==
“我想知道arr.sort()是否正在将数字转换为对象,尽管有一个可以处理数字的比较函数。”---为什么不检查?@rcgldr不,我的意思是-你是在假设V8是如何实现的,而不是检查它。“转换可能会导致一定程度的间接性(如C中的指针),从而增加排序时间。”---这句话毫无意义,因为你可以看到上面的链接。@zerkms-我在我的答案中添加了一个带有比较功能的合并排序,它仍然比本机排序快得多。@zzzzBov-我更新了我的答案,使之包含了本机排序速度慢的一个合理原因。这个缺陷已经存在多年了,它来自谷歌,这家臭名昭著的公司让受访者反刍排序算法。不确定这是更讽刺还是更可悲。
native sort - failed for out of memory.
Relu's merge sort - 1.8 seconds
Relu's quick sort - 1.3 seconds
optimized merge sort - 1.4 seconds
optimized merge sort with compare - 1.8 seconds
native sort - 5.3 seconds
Relu's merge sort - 2.1 seconds
Relu's quick sort - 1.8 seconds
optimized merge sort - 1.6 seconds
optimized merge sort with compare - 1.7 seconds