web-dev-qa-db-fra.com

Pourquoi insérer au milieu d'une liste chaînée O (1)?

Selon le article Wikipedia sur les listes chaînées , l'insertion au milieu d'une liste chaînée est considérée comme O (1). Je pense que ce serait O (n). N'auriez-vous pas besoin de localiser le nœud qui pourrait se trouver vers la fin de la liste?

Cette analyse ne tient-elle pas compte de la découverte de l'opération du nœud (bien qu'elle soit nécessaire) et seulement de l'insertion elle-même?

[~ # ~] éditez [~ # ~] :

Les listes liées présentent plusieurs avantages par rapport aux tableaux. L'insertion d'un élément à un point spécifique d'une liste est une opération à temps constant, tandis que l'insertion dans un tableau peut nécessiter le déplacement de la moitié des éléments, ou davantage.

La déclaration ci-dessus est un peu trompeuse pour moi. Corrigez-moi si je me trompe, mais je pense que la conclusion devrait être:

Tableaux:

  • Recherche du point d'insertion/suppression O (1)
  • Exécution de l'insertion/suppression O (n)

Listes liées:

  • Recherche du point d'insertion/suppression O (n)
  • Exécution de l'insertion/suppression O (1)

Je pense que la seule fois où vous n'auriez pas à trouver la position est si vous gardiez une sorte de pointeur (comme avec la tête et la queue dans certains cas). Nous ne pouvons donc pas dire catégoriquement que les listes liées battent toujours les tableaux pour les options d'insertion/suppression.

90
Rob Sobers

Vous avez raison, l'article considère "l'indexation" comme une opération distincte. L'insertion est donc elle-même O (1), mais arriver à ce nœud central est O (n).

101
CookieOfFortune

L'insertion elle-même est O (1). Node recherche est O (n).

24
Evansbee

Non, lorsque vous décidez d'insérer, il est supposé que vous êtes déjà en train de parcourir la liste.

Les opérations sur les listes liées sont souvent effectuées de telle manière qu'elles ne sont pas vraiment traitées comme une "liste" générique, mais comme une collection de nœuds - pensez au nœud lui-même comme l'itérateur de votre boucle principale. Ainsi, lorsque vous parcourez la liste, vous remarquez dans le cadre de votre logique métier qu'un nouveau nœud doit être ajouté (ou un ancien supprimé) et vous le faites. Vous pouvez ajouter 50 nœuds en une seule itération et chacun de ces nœuds est juste O(1) le temps de dissocier deux nœuds adjacents et d'insérer votre nouveau ..

Edit: Man, vous tapez un deuxième paragraphe et tout d'un coup au lieu d'être le premier répondant, vous êtes le 5ème à dire la même chose que les 4 premiers!

21
Bill K

À des fins de comparaison avec un tableau, ce que montre ce graphique, c'est O(1) parce que vous n'avez pas à déplacer tous les éléments après le nouveau nœud.

Alors oui, ils supposent que vous avez déjà le pointeur sur ce nœud, ou que l'obtention du pointeur est triviale. En d'autres termes, le problème est posé: "noeud donné en X, quel est le code à insérer après ce noeud?" Vous pouvez commencer au point d'insertion.

6
Joel Coehoorn

L'insertion dans une liste chaînée est différente de son itération. Vous ne localisez pas l'élément, vous réinitialisez les pointeurs pour y placer l'élément. Peu importe qu'il soit inséré près de l'extrémité avant ou près de l'extrémité, l'insertion implique toujours la réaffectation des pointeurs. Cela dépendra de la façon dont il a été implémenté, bien sûr, mais c'est la force des listes - vous pouvez les insérer facilement. L'accès via index est l'endroit où un tableau brille. Pour une liste, cependant, ce sera généralement O(n) pour trouver le nième élément. Du moins, c'est ce dont je me souviens de l'école.

5
itsmatt

Parce qu'il n'implique aucune boucle.

L'insertion est comme:

  • insérer un élément
  • lien vers le précédent
  • lien vers le suivant
  • terminé

c'est du temps constant dans tous les cas.

Par conséquent, l'insertion de n éléments l'un après l'autre est O (n).

3
Tomalak

Cette analyse ne tient-elle pas compte de la découverte de l'opération du nœud (bien qu'elle soit nécessaire) et seulement de l'insertion elle-même?

Tu l'as eu. L'insertion à un moment donné suppose que vous détenez déjà un pointeur sur l'élément que vous souhaitez insérer après:

InsertItem(item * newItem, item * afterItem)
3
e.James

L'insertion est O(1) une fois que vous savez où vous allez le mettre.

2

Non, cela ne tient pas compte de la recherche. Mais si vous avez déjà un pointeur sur un élément au milieu de la liste, l'insertion à ce point est O (1).

Si vous devez le rechercher, vous devrez ajouter le temps de recherche, qui devrait être O (n).

2
T.E.D.

L'article concerne la comparaison de tableaux avec des listes. Trouver la position d'insertion pour les tableaux et les listes est O (N), donc l'article l'ignore.

0
anon

O (1) dépend du fait que vous avez un élément où vous allez insérer le nouvel élément. (avant ou après). Si vous ne le faites pas, c'est O(n) parce que vous devez trouver cet article.

0
Glenn

Je pense que c'est juste un cas de ce que vous choisissez de compter pour la notation O(). Dans le cas de l'insertion de l'opération normale pour compter, il s'agit d'opérations de copie. Avec un tableau, l'insertion au milieu implique de copier tout ce qui se trouve au-dessus de l'emplacement dans la mémoire. Avec une liste liée, cela devient la définition de deux pointeurs. Vous devez trouver l'emplacement, peu importe quoi insérer.

0
workmad3

Si vous avez la référence du nœud à insérer après l'opération est O(1) pour une liste chaînée.
Pour un tableau, c'est toujours O(n) puisque vous devez déplacer tous les nœuds conséquents.

0

Les cas les plus courants sont probablement à insérer au début ou à la fin de la liste (et les extrémités de la liste peuvent ne pas prendre de temps à trouver).

Comparez cela à l'insertion d'éléments au début ou à la fin d'un tableau (ce qui nécessite de redimensionner le tableau s'il est à la fin, ou de redimensionner et de déplacer tous les éléments s'il est au début).

0
ChrisW