【发布时间】:2021-12-08 08:35:16
【问题描述】:
我有一个已排序的 JavaScript 数组,并且想在数组中再插入一项,这样生成的数组就会保持排序状态。我当然可以实现一个简单的快速排序式插入函数:
var array = [1,2,3,4,5,6,7,8,9];
var element = 3.5;
function insert(element, array) {
array.splice(locationOf(element, array) + 1, 0, element);
return array;
}
function locationOf(element, array, start, end) {
start = start || 0;
end = end || array.length;
var pivot = parseInt(start + (end - start) / 2, 10);
if (end-start <= 1 || array[pivot] === element) return pivot;
if (array[pivot] < element) {
return locationOf(element, array, pivot, end);
} else {
return locationOf(element, array, start, pivot);
}
}
console.log(insert(element, array));
[WARNING] 此代码在尝试插入数组开头时存在错误,例如insert(2, [3, 7 ,9]) 产生不正确的 [ 3, 2, 7, 9 ]。
但是,我注意到 Array.sort 函数的实现可能会为我做这件事,而且是原生的:
var array = [1,2,3,4,5,6,7,8,9];
var element = 3.5;
function insert(element, array) {
array.push(element);
array.sort(function(a, b) {
return a - b;
});
return array;
}
console.log(insert(element, array));
是否有充分的理由选择第一个实现而不是第二个?
编辑:请注意,对于一般情况,O(log(n)) 插入(在第一个示例中实现)将比通用排序算法快;然而,这不一定是 JavaScript 的特殊情况。请注意:
- 几种插入算法的最佳情况是 O(n),这仍然与 O(log(n)) 有很大不同,但不如 O(n log(n)) 糟糕,如下所述。这将归结为使用的特定排序算法(请参阅Javascript Array.sort implementation?)
- JavaScript 中的排序方法是一个原生函数,因此可能会实现巨大的好处——对于合理大小的数据集,具有巨大系数的 O(log(n)) 仍然可能比 O(n) 差得多。
【问题讨论】:
-
在第二个实现中使用 splice 有点浪费。为什么不使用推送?
-
好点,我只是从第一个复制过来的。
-
任何包含
splice()的内容(例如您的第一个示例)已经是 O(n)。即使它没有在内部创建整个数组的新副本,如果要将元素插入位置 0,它也可能必须将所有 n 项分流回 1 位置。也许它很快,因为它是一个本机函数并且常量是低,但它仍然是 O(n)。 -
另外,为了供使用此代码的人将来参考,该代码在尝试插入数组开头时存在错误。进一步向下查找更正后的代码。
-
不要使用
parseInt,而是使用Math.floor。Math.floor比parseInt快得多:jsperf.com/test-parseint-and-math-floor
标签: javascript algorithm sorting