web-dev-qa-db-fra.com

Complexité d'exécution JavaScript des fonctions de tableau

La complexité d'exécution est-elle définie par la norme JS sur les fonctions Array courantes comme Push, pop, shift, slice ou splice? Esp. Je souhaite supprimer et insérer des entrées à des positions aléatoires. Si la complexité n'est pas définie, à quoi puis-je m'attendre, par ex. en V8?

(Cette question a été inspirée par cette . De plus, cette référence , publiée ici , me rend également curieux, mais c'est peut-être un phénomène sans rapport. )

(Une question très connexe est ici . Cependant, l'un des commentaires sur la réponse acceptée dit qu'elle est erronée maintenant. De plus, la réponse acceptée n'a aucune référence que la norme la définit vraiment de cette façon .).

37
Albert

La spécification ECMA ne spécifie pas de complexité de délimitation, cependant, vous pouvez en dériver une à partir des algorithmes de la spécification.

Push est O (1), cependant, en pratique, il rencontrera un O (N) coûts de copie aux limites définies par le moteur, car la baie de logements doit être réaffecté. Ces limites sont généralement logarithmiques.

pop est O (1) avec une mise en garde similaire à Push mais la copie O (N) est rarement rencontrée car elle est souvent plié en garbage collection (par exemple, un collecteur de copie ne peut copier que la partie utilisée d'un tableau).

shift est au pire O (N) mais il peut, dans des cas particuliers, être implémenté comme O (1) au prix d'un ralentissement de l'indexation donc Votre kilométrage peut varier.

slice est O (N) N est end - start. Pas une énorme opportunité d'optimisation ici sans ralentir considérablement les écritures sur les deux tableaux.

splice est, dans le pire des cas, O (N). Il existe des techniques de stockage en baie qui divisent N par une constante mais elles ralentissent considérablement l'indexation. Si un moteur utilise de telles techniques, vous remarquerez peut-être des opérations inhabituellement lentes car il bascule entre les techniques de stockage déclenchées par les changements de modèle d'accès.

Celui que vous n'avez pas mentionné est sort. C'est, dans le cas moyen, O (N log N). Cependant, selon l'algorithme choisi par le moteur, vous pourriez obtenir O (N ^ 2) dans certains cas. Par exemple, si le moteur utilise QuickSort (même avec un retard vers InsertionSort), il a des cas bien connus N ^ 2. Cela pourrait être une source de DoS pour votre application. S'il s'agit d'un problème, limitez la taille des tableaux que vous triez (peut-être en fusionnant les sous-tableaux) ou renflouez-le vers HeapSort.

73
chuckj

Juste une remarque, il est possible d'implémenter les méthodes shift/unshift, Push/pop dans O(1) en utilisant Structure de données RingBuffer (iow CircularQueue/CircularBuffer). Ce serait O(1) dans le pire des cas, chaque fois que le tampon circulaire n'est pas requis pour croître. Quelqu'un a-t-il réellement mesuré les performances de ces opérations? Il vaut toujours mieux savoir plutôt que de deviner ...

0
Lu4