Perché l'inserimento nel mezzo di un elenco collegato O (1)?


105

Secondo l' articolo di Wikipedia sugli elenchi collegati , l'inserimento al centro di un elenco collegato è considerato O (1). Penso che sarebbe O (n). Non avresti bisogno di individuare il nodo che potrebbe essere vicino alla fine dell'elenco?

Questa analisi non tiene conto del ritrovamento dell'operazione del nodo (sebbene sia necessaria) e solo dell'inserimento stesso?

MODIFICA :

Gli elenchi collegati hanno diversi vantaggi rispetto agli array. L'inserimento di un elemento in un punto specifico di un elenco è un'operazione a tempo costante, mentre l'inserimento in un array può richiedere lo spostamento di metà degli elementi o più.

La dichiarazione di cui sopra è un po 'fuorviante per me. Correggimi se sbaglio, ma penso che la conclusione dovrebbe essere:

Array:

  • Trovare il punto di inserimento / cancellazione O (1)
  • Esecuzione dell'inserimento / cancellazione O (n)

Elenchi collegati:

  • Trovare il punto di inserimento / cancellazione O (n)
  • Esecuzione dell'inserimento / cancellazione O (1)

Penso che l'unica volta in cui non dovresti trovare la posizione è se tieni una sorta di puntatore ad essa (come con la testa e la coda in alcuni casi). Quindi non possiamo affermare apertamente che gli elenchi collegati battono sempre gli array per le opzioni di inserimento / eliminazione.

Risposte:


113

Hai ragione, l'articolo considera "Indicizzazione" come un'operazione separata. Quindi l'inserimento è esso stesso O (1), ma arrivare a quel nodo centrale è O (n).


3
Il che fa una differenza maggiore quando si inserisce più di 1 oggetto nella stessa posizione ...
Ha QUIT - Anony-Mousse

@ Anony-Mousse puoi spiegarmi un po 'di più? cioè dobbiamo trovare la posizione di inserimento solo una volta quando si inseriscono più oggetti?
MyTitle

2
È O (n) nella dimensione dell'elenco esistente, non nel numero di inserimenti che prevedi di fare lì.
HA USCITO - Anony-Mousse

28

L'inserimento stesso è O (1). La ricerca del nodo è O (n).


25

No, quando decidi di voler inserire, si presume che tu sia già nel mezzo dell'iterazione dell'elenco.

Le operazioni sugli elenchi collegati vengono spesso eseguite in modo tale da non essere realmente trattate come un "elenco" generico, ma come una raccolta di nodi: pensa al nodo stesso come all'iteratore del ciclo principale. Quindi, mentre sfogli l'elenco, noti come parte della logica aziendale che è necessario aggiungere un nuovo nodo (o eliminare uno vecchio) e lo fai. Puoi aggiungere 50 nodi in una singola iterazione e ciascuno di questi nodi è solo O (1) il tempo necessario per scollegare due nodi adiacenti e inserire quello nuovo ..

Modifica: amico, digiti un secondo paragrafo e all'improvviso invece di essere il primo risponditore sei il quinto dicendo la stessa cosa del primo 4!


1
Ah sì che fa schifo ... ho fatto +1 al tuo perché vale la pena affermare che la complessità dell'inserimento di elenchi collegati è considerata nel contesto di essere già al puntatore desiderato.
Daniel Macias

6

Ai fini del confronto con un array, che è ciò che mostra il grafico, è O (1) perché non è necessario spostare tutti gli elementi dopo il nuovo nodo.

Quindi sì, presumono che tu abbia già il puntatore a quel nodo, o che ottenere il puntatore sia banale. In altre parole, il problema è affermato: " dato nodo in X , qual è il codice da inserire dopo questo nodo?" Si inizia dal punto di inserimento.


5

L'inserimento in un elenco collegato è diverso dall'iterazione su di esso. Non stai individuando l'elemento, stai reimpostando i puntatori per inserire l'elemento lì. Non importa se verrà inserito vicino al front-end o vicino alla fine, l'inserimento comporta comunque la riassegnazione dei puntatori. Dipenderà da come è stato implementato, ovviamente, ma questa è la forza degli elenchi: puoi inserirli facilmente. L'accesso tramite indice è dove un array brilla. Per un elenco, tuttavia, tipicamente sarà O (n) per trovare l'ennesimo elemento. Almeno questo è quello che ricordo dalla scuola.


3

Perché non comporta alcun looping.

L'inserimento è come:

  • inserire elemento
  • collegamento al precedente
  • collegamento a successivo
  • fatto

questo è in ogni caso un tempo costante.

Di conseguenza, l'inserimento di n elementi uno dopo l'altro è O (n).


3

Questa analisi non tiene conto del ritrovamento dell'operazione del nodo (sebbene sia necessaria) e solo dell'inserimento stesso?

Avete capito bene. L'inserimento in un dato punto presuppone che tu abbia già premuto un puntatore all'elemento che desideri inserire dopo:

InsertItem(item * newItem, item * afterItem)


2

No, non tiene conto della ricerca. Ma se hai già in mano un puntatore a un elemento al centro della lista, l'inserimento in quel punto è O (1).

Se devi cercarlo, dovresti aggiungere il tempo per la ricerca, che dovrebbe essere O (n).


0

L'articolo riguarda il confronto di array con elenchi. Trovare la posizione di inserimento sia per gli array che per gli elenchi è O (N), quindi l'articolo lo ignora.


1
Trovare il punto di inserimento di un array non sarebbe O (1)? Poiché gli array sono archiviati in una memoria contigua, tutto ciò che deve fare è aggiungere l'offset.
Rob Sobers,

@ vg1890 - Devi prima trovare l'offset.

0

O (1) dipende da questo fatto che hai un elemento in cui inserirai il nuovo elemento. (prima o dopo). Se non lo fai, è O (n) perché devi trovare quell'oggetto.


0

Penso che sia solo un caso di ciò che scegli di contare per la notazione O (). Nel caso di inserimento la normale operazione da contare è quella di copia. Con un array, l'inserimento nel mezzo implica la copia di tutto ciò che si trova sopra la posizione in memoria. Con un elenco collegato, questo diventa l'impostazione di due puntatori. Devi trovare la posizione indipendentemente da cosa inserire.


0

Se hai il riferimento del nodo da inserire dopo l'operazione è O (1) per una lista collegata.
Per un array è ancora O (n) poiché devi spostare tutti i nodi consecutivi.


0

I casi più comuni sono probabilmente l'inserimento all'inizio o alla fine dell'elenco (e le estremità dell'elenco potrebbero non richiedere tempo per essere trovate).

Confrontalo con l'inserimento di elementi all'inizio o alla fine di un array (che richiede il ridimensionamento dell'array se è alla fine, o il ridimensionamento e lo spostamento di tutti gli elementi se è all'inizio).


È possibile fare in modo che l'inserimento di elementi alla fine di un array sia O (1) se si mantiene un buffer di elementi vuoti alla fine, anche se occasionalmente gli inserimenti saranno ancora O (1). La maggior parte delle collezioni lo fa. Èpossibile anche far sì che gli elementi di inertizzazione all'inizio di un array siano O (1) cambiando l'operatore di indice per restituire il numero dell'elemento (n + x)% len, dove x è il numero di volte in cui hai inserito gli elementi all'inizio della lista. Le deques a volte sono implementate in questo modo (ma a volte sono anche implementate con elenchi doppiamente concatenati.
Brian
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.