我有一个已排序的JavaScript数组,并且想在该数组中再插入一个项目,以使结果数组保持排序状态。我当然可以实现一个简单的quicksort样式的插入函数:
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));
[警告] 尝试插入到数组的开头时,此代码存在错误,例如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实现?)
- JavaScript中的sort方法是一个本机函数,因此潜在地实现了巨大的好处-对于合理大小的数据集,具有巨大系数的O(log(n))仍然比O(n)差很多。
splice()
(例如您的第一个示例)已经是O(n)。即使它没有在内部创建整个数组的新副本,如果要将元素插入位置0,它也可能必须将所有n个项目分流回1位置。也许这是快速的,因为它是一个本机函数,并且常量是低,但仍为O(n)。