J'ai un tableau JavaScript trié et je souhaite insérer un autre élément dans le tableau afin que le tableau résultant reste trié. Je pourrais certainement implémenter une simple fonction d'insertion de type tri rapide:
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));
[AVERTISSEMENT] ce code a un bogue en essayant d'insérer au début du tableau, par exemple insert(2, [3, 7 ,9]
) produit incorrect [3, 2, 7, 9].
Cependant, j'ai remarqué que les implémentations de la fonction Array.sort pourraient potentiellement le faire pour moi, et de manière native:
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));
Y a-t-il une bonne raison de choisir la première implémentation plutôt que la seconde?
Edit : Notez que pour le cas général, une insertion O (log (n)) (telle qu'implémentée dans le premier exemple) sera plus rapide qu'un algorithme de tri générique; cependant ce n'est pas nécessairement le cas pour JavaScript en particulier. Notez que:
- Le meilleur cas pour plusieurs algorithmes d'insertion est O (n), qui est toujours significativement différent de O (log (n)), mais pas aussi mauvais que O (n log (n)) comme mentionné ci-dessous. Cela reviendrait à l'algorithme de tri particulier utilisé (voir l' implémentation Javascript Array.sort? )
- La méthode de tri en JavaScript est une fonction native, donc potentiellement réaliser d'énormes avantages - O (log (n)) avec un coefficient énorme peut encore être bien pire que O (n) pour des ensembles de données de taille raisonnable.
splice()
(par exemple votre premier exemple) est déjà O (n). Même s'il ne crée pas en interne une nouvelle copie du tableau entier, il doit potentiellement dériver tous les n éléments d'une position en arrière si l'élément doit être inséré en position 0. Peut-être que c'est rapide parce que c'est une fonction native et que la constante est faible, mais c'est quand même O (n).
parseInt
utilisation à la Math.floor
place. Math.floor
est beaucoup plus rapide que parseInt
: jsperf.com/test-parseint-and-math-floor