JavaScript对象充当数组和字典的运行时的JavaScript排序

时间:2017-01-11 21:20:06

标签: javascript algorithm sorting v8

编辑:看起来我在下面写的是Pigeonhole Sort的一种形式。

我一直在研究JavaScript Arrays是如何真正特殊的对象,另外还有有序迭代器(因为它们是集合)。

因此,这段代码是可能的:

let inputArray = []; // inputArray.length === n
// non-duplicate entries for the sake of this question (easy to alter)
let sparse = new Array(); // Sets up as dictionary

// O(n)
inputArray.forEach(function(entry) { // Uses Dictionary mode
    sparse[entry] = entry; // O(1) 
});

// O(n) (actual is n log n)
let sortedArray = [];
for (let entry of sparse) { // Uses Array mode
    sortedArray.push(entry); // O(1)
}

但是由于排序算法具有最快的O(n log(n))运行时间,因此JavaScript对象字典模式和数组模式之间的转换必须减慢它的速度。我测试了它,它确实按预期减慢了(尽管它比原始.sort()更快),但它只涵盖toString()的排序,所以很明显我会使用原生版本。

所以我有以下问题:

  1. 在上面的代码中,它是否专门用于O(n log(n))算法?
  2. 你可以链接我的源代码吗?以V8为例。
  3. 我假设在for...of阶段它将是一个懒惰的迭代器创建或访问,但我很乐意看到代码及其原因。

2 个答案:

答案 0 :(得分:2)

只有基于比较的排序永远不会比O(n log n)快。在您的代码中,排序发生在sparse[entry] = entry行,您可以在其中进行基于索引的排序。这在O(n)时间内有效,但有一些限制:主要是,只有事先知道值的范围才有效。在这种情况下,隐式定义的有效值范围是有效数组索引的集合,即从0到2 ^ 32-1的整数。(尝试添加负数,或(非整数)double或字符串,到您的输入数组。)

更多澄清:

  • new Array()未在字典模式下设置任何内容。您可以使用var sparse = [];,您的代码将完全相同。根据引擎启发式方法,后续使用模式可能会也可能不会将数组转换为字典模式,但您不会发现行为上的差异。

  • for..offor..in具有相同的迭代顺序(默认情况下)。他们最大的区别之一是for..in遍历(其中规定了类型字符串),而for..of遍历 (你有什么类型的)。 (尝试使用[3, 4, "5"]for..in将返回"0", "1", "2"for..of将返回3, 4, "5"。)

  • for..in循环的最大问题是它们包含来自原型链的东西。如果您包含的任何库都Array.prototype.myFancyFunction = ...,那么您在阵列上的所有for..in循环将返回一个超出预期的元素; - )

答案 1 :(得分:0)

看来for...of在通过可枚举属性时,必须检查每个连续的数字(键),直到它遇到length个元素。如果这是排序的(并且在数组模式下),那么迭代器的下一个元素很容易,但由于它没有排序(因为它是在映射模式下创建的),它必须检查每个潜在的数字。 order(0,1,... [last defined element])。我没有费心检查源代码,但从更多的时间测试和打印状态来看,这似乎就是答案。