Vai al contenuto principale

Liste collegate in Python: tutorial con esempi

Impara tutto quello che devi sapere sulle liste collegate: quando usarle, i tipi e l’implementazione in Python.
Aggiornato 22 lug 2026  · 9 min leggi

Esplora con l'AI

Apri in ChatGPTApri in ClaudeApri in Perplexity

Una lista collegata è una struttura dati che svolge un ruolo cruciale nell’organizzazione e nella gestione dei dati. Contiene una serie di nodi memorizzati in posizioni casuali della memoria, consentendo una gestione efficiente della memoria. Ogni nodo in una lista collegata contiene due componenti principali: la parte dei dati e un riferimento al nodo successivo nella sequenza.

Se a prima vista questo concetto ti sembra complesso, niente panico!

Lo scomporremo ai fondamentali per spiegare cosa sono le liste collegate, perché le usiamo e i vantaggi specifici che offrono.

Perché le liste collegate?

Le liste collegate sono state create per superare vari svantaggi legati all’archiviazione dei dati in liste e array tradizionali, come descritto di seguito:

Facilità di inserimento e cancellazione

Nelle liste, inserire o eliminare un elemento in una posizione diversa dalla fine richiede di spostare tutti gli elementi successivi in una posizione diversa. Questo processo ha complessità temporale O(n) e può degradare notevolmente le prestazioni, soprattutto man mano che la lista cresce. Se non hai ancora familiarità con il funzionamento delle liste o con la loro implementazione, puoi leggere il nostro tutorial sulle liste in Python.

Le liste collegate, invece, funzionano in modo diverso. Memorizzano gli elementi in varie posizioni non contigue di memoria e li connettono tramite puntatori ai nodi successivi. Questa struttura consente alle liste collegate di aggiungere o rimuovere elementi in qualsiasi posizione semplicemente modificando i collegamenti per includere un nuovo elemento o saltare quello eliminato.

Una volta che hai un riferimento diretto al nodo nel punto di inserimento o cancellazione, l’operazione in sé è O(1). Tuttavia, trovare quella posizione richiede comunque una traversata O(n), quindi il vantaggio O(1) si applica solo quando possiedi già un puntatore al nodo rilevante (ad esempio quando lavori sulla testa della lista).

Dimensione dinamica

Le liste di Python sono array dinamici, il che significa che offrono la flessibilità di modificarne la dimensione.

Tuttavia, questo processo comporta una serie di operazioni complesse, tra cui riallocare l’array in un nuovo blocco di memoria più grande. Tale riallocazione è inefficiente poiché gli elementi vengono copiati in un nuovo blocco, potenzialmente allocando più spazio del necessario nell’immediato.

Al contrario, le liste collegate possono crescere e ridursi dinamicamente senza bisogno di riallocazione o ridimensionamento. Questo le rende una scelta preferibile per attività che richiedono elevata flessibilità.

Efficienza della memoria

Le liste allocano la memoria per tutti i loro elementi in un blocco contiguo. Se una lista deve crescere oltre la sua dimensione iniziale, deve allocare un nuovo blocco di memoria contiguo più grande e poi copiare tutti gli elementi esistenti in questo nuovo blocco. Questo processo è dispendioso in tempo e inefficiente, soprattutto per liste di grandi dimensioni. D’altra parte, se la dimensione iniziale della lista è sovrastimata, la memoria inutilizzata viene sprecata.

Al contrario, le liste collegate allocano la memoria per ogni elemento separatamente. Questa struttura porta a un migliore utilizzo della memoria, poiché la memoria per i nuovi elementi può essere allocata man mano che vengono aggiunti.

Quando dovresti usare le liste collegate?

Sebbene le liste collegate offrano alcuni vantaggi rispetto a liste e array tradizionali, come dimensione dinamica ed efficienza della memoria, presentano anche dei limiti. Poiché per ogni elemento devono essere memorizzati i puntatori al nodo successivo, l’uso di memoria per elemento è più alto con le liste collegate. Inoltre, questa struttura dati non consente l’accesso diretto ai dati. Accedere a un elemento richiede una traversata sequenziale dall’inizio della lista, con complessità temporale di ricerca O(n).

La scelta tra una lista collegata o un array dipende dalle esigenze specifiche dell’applicazione. Le liste collegate sono più utili quando:

  • Devi inserire ed eliminare spesso molti elementi
  • La dimensione dei dati è imprevedibile o soggetta a frequenti cambiamenti
  • L’accesso diretto agli elementi non è un requisito
  • Il dataset contiene elementi o strutture di grandi dimensioni

Tipi di liste collegate

Esistono tre tipi di liste collegate, ognuna con vantaggi specifici per scenari diversi. Questi tipi sono:

Liste semplicemente collegate (singly-linked)

Immagine di una lista semplicemente collegata

Lista semplicemente collegata

Una lista semplicemente collegata è il tipo più semplice di lista collegata, in cui ogni nodo contiene dei dati e un riferimento al nodo successivo nella sequenza. Può essere attraversata in una sola direzione: dalla testa (il primo nodo) alla coda (l’ultimo nodo).

Ogni nodo in una lista semplicemente collegata è tipicamente composto da due parti:

  • Dati: Le informazioni effettive memorizzate nel nodo.
  • Puntatore al successivo: Un riferimento al nodo successivo. Il puntatore al successivo dell’ultimo nodo è solitamente impostato a null.

Poiché queste strutture dati possono essere attraversate in una sola direzione, l’accesso a un elemento specifico per valore o indice richiede di partire dalla testa e muoversi sequenzialmente tra i nodi fino a trovare quello desiderato. Questa operazione ha complessità temporale O(n), risultando meno efficiente per liste grandi.

Inserire ed eliminare un nodo all’inizio di una lista semplicemente collegata è molto efficiente, con complessità O(1). Tuttavia, l’inserimento e la cancellazione nel mezzo o alla fine richiedono di attraversare la lista fino a quel punto, portando a una complessità O(n).

Il design delle liste semplicemente collegate le rende una struttura dati utile quando si eseguono operazioni che avvengono all’inizio della lista.

Liste doppiamente collegate (doubly-linked)

Immagine di una lista doppiamente collegata

Lista doppiamente collegata

Uno svantaggio delle liste semplicemente collegate è che possiamo attraversarle solo in una direzione e non possiamo tornare al nodo precedente se necessario. Questo vincolo limita la possibilità di eseguire operazioni che richiedono una navigazione bidirezionale.

Le liste doppiamente collegate risolvono questo problema incorporando un puntatore aggiuntivo all’interno di ogni nodo, garantendo che la lista possa essere attraversata in entrambe le direzioni. Ogni nodo in una lista doppiamente collegata contiene tre elementi: i dati, un puntatore al nodo successivo e un puntatore al nodo precedente.

Liste collegate circolari

Immagine di una lista collegata circolare

Lista collegata circolare

Le liste collegate circolari sono una forma specializzata di lista collegata in cui l’ultimo nodo punta di nuovo al primo, creando una struttura circolare. Questo significa che, a differenza delle liste semplici e doppie viste finora, la lista circolare non termina; invece, fa un loop.

La natura ciclica delle liste collegate circolari le rende ideali per scenari che devono essere percorsi continuamente, come giochi da tavolo che tornano dall’ultimo giocatore al primo, o in algoritmi informatici come lo scheduling round-robin.

Riepilogo delle complessità temporali

È utile vedere a colpo d’occhio come le liste collegate si confrontano con le liste di Python:

Operazione Lista semplicemente collegata Array/Lista Python
Accesso per indice O(n) O(1)
Ricerca per valore O(n) O(n)
Inserimento all’inizio O(1) O(n)
Inserimento alla fine O(n) O(1) ammortizzato
Inserimento in mezzo O(n) O(n)
Eliminazione all’inizio O(1) O(n)
Eliminazione alla fine O(n) O(1) ammortizzato

Il punto chiave: le liste collegate vincono su inserimenti ed eliminazioni in testa (O(1)), ma perdono su tutto il resto. Se non stai aggiungendo o rimuovendo spesso elementi all’inizio della tua struttura dati, una normale lista Python è probabilmente la scelta migliore.

Come creare una lista collegata in Python

Ora che abbiamo capito cosa sono le liste collegate, perché le usiamo e le loro varianti, passiamo a implementare queste strutture dati in Python. Il notebook per questo tutorial è disponibile anche in questo workbook DataLab; se ne crei una copia, puoi modificare ed eseguire il codice. È un’ottima opzione se riscontri problemi nell’eseguire il codice in autonomia!

Inizializzare un nodo

Come abbiamo visto, un nodo è un elemento nella lista collegata che memorizza dati e un riferimento al nodo successivo nella sequenza. Ecco come puoi definire un nodo in Python:

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

    def __repr__(self):
        return f"Node({self.data})"

Il codice sopra inizializza un nodo eseguendo due azioni principali: all’attributo “data” del nodo viene assegnato un valore che rappresenta l’informazione effettiva che il nodo deve contenere. L’attributo “next” rappresenta l’indirizzo del nodo successivo. Attualmente è impostato a None, a significare che non è collegato ad alcun altro nodo nella lista. Man mano che aggiungeremo nuovi nodi alla lista collegata, questo attributo verrà aggiornato per puntare al nodo successivo.

Creare una classe per la lista collegata

Successivamente, dobbiamo creare la classe della lista collegata. Questa incapsulerà tutte le operazioni per gestire i nodi, come inserimento e rimozione. Inizieremo inizializzando la lista collegata:

class LinkedList:
    def __init__(self):
        self.head = None  # Initialize head as None

Impostando self.head a None, stiamo dichiarando che la lista collegata è inizialmente vuota e non ci sono nodi a cui puntare. Procederemo ora a popolare la lista inserendo nuovi nodi.

Inserire un nuovo nodo all’inizio di una lista collegata

All’interno della classe LinkedList, aggiungeremo un metodo per creare un nuovo nodo e posizionarlo all’inizio della lista:

    def insertAtBeginning(self, new_data):
        new_node = Node(new_data)  # Create a new node 
        new_node.next = self.head  # Next for new node becomes the   current head
        self.head = new_node  # Head now points to the new node

Ogni volta che chiami il metodo sopra, viene creato un nuovo nodo con i dati che specifichi. Il puntatore “next” di questo nuovo nodo è impostato sull’attuale testa della lista, il che posiziona questo nodo davanti ai nodi esistenti. Infine, il nodo appena creato diventa la testa della lista.

Ora popoleremo questa lista collegata con una serie di parole per comprendere meglio come funziona l’operazione di inserimento. Per farlo, creiamo prima un metodo pensato per attraversare e stampare il contenuto della lista:

    def printList(self):
        temp = self.head # Start from the head of the list
        while temp:
            print(temp.data,end=' ') # Print the data in the current node
            temp = temp.next # Move to the next node
        print()  # Ensures the output is followed by a new line

Il metodo sopra stamperà il contenuto della nostra lista collegata. Procediamo ora a usare i metodi che abbiamo definito per popolare la lista con una serie di parole: “the quick brown fox”.

if __name__ == '__main__':
    # Create a new LinkedList instance
    llist = LinkedList()

    # Insert each letter at the beginning using the method we created
    llist.insertAtBeginning('fox') 
    llist.insertAtBeginning('brown') 
    llist.insertAtBeginning('quick')  
    llist.insertAtBeginning('the')  

    # Now 'the' is the head of the list, followed by 'quick', then 'brown' and 'fox'

    # Print the list
    llist.printList()

Le righe di codice sopra dovrebbero produrre il seguente output:

"the quick brown fox"

Inserire un nuovo nodo alla fine di una lista collegata

Ora creeremo un metodo chiamato insertAtEnd all’interno della classe LinkedList, per creare un nuovo nodo alla fine della lista. Se la lista è vuota, il nuovo nodo diventerà la testa della lista. Altrimenti, verrà aggiunto al nodo attualmente ultimo nella lista. Vediamo come funziona in pratica:

    def insertAtEnd(self, new_data):
        new_node = Node(new_data)
        if self.head is None:
            self.head = new_node
            return
        last = self.head
        while last.next:
            last = last.next
        last.next = new_node

Il metodo sopra inizia creando un nuovo nodo. Quindi verifica se la lista è vuota e, in tal caso, assegna il nuovo nodo come testa di quella lista. Altrimenti, attraversa la lista per trovare l’ultimo nodo e imposta il puntatore di quest’ultimo sul nuovo nodo.

Ora dobbiamo includere questo metodo nella nostra classe LinkedList e usarlo per aggiungere una parola alla fine della lista. Per farlo, modifica la funzione main in questo modo:

if __name__ == '__main__':
    llist = LinkedList()

    # Insert words at the beginning
    llist.insertAtBeginning('fox')
    llist.insertAtBeginning('brown')
    llist.insertAtBeginning('quick')
    llist.insertAtBeginning('the')

    # Insert a word at the end
    llist.insertAtEnd('jumps')

    # Print the list
    llist.printList()

Nota che abbiamo semplicemente chiamato il metodo insertAtEnd per stampare la parola “jumps” alla fine della lista. Il codice sopra dovrebbe produrre il seguente output:

"the quick brown fox jumps"

Eliminare un nodo dall’inizio di una lista collegata

Eliminare il primo nodo di una lista collegata è semplice, poiché comporta semplicemente il puntare la testa della lista al secondo nodo. In questo modo, il primo nodo non farà più parte della lista. Per farlo, includi il seguente metodo nella classe LinkedList:

def deleteFromBeginning(self):
    if self.head is None:
        return "The list is empty" # If the list is empty, return this string
    self.head = self.head.next  # Otherwise, remove the head by making the next node the new head

Eliminare un nodo dalla fine di una lista collegata

Per eliminare l’ultimo nodo di una lista collegata, dobbiamo attraversare la lista per trovare il penultimo nodo e cambiare il suo puntatore “next” a None. In questo modo, l’ultimo nodo non farà più parte della lista. Copia e incolla il seguente metodo nella tua classe LinkedList per farlo:

def deleteFromEnd(self):
    if self.head is None:
        return "The list is empty" 
    if self.head.next is None:
        self.head = None  # If there's only one node, remove the head by making it None
        return
    temp = self.head
    while temp.next.next:  # Otherwise, go to the second-last node
        temp = temp.next
    temp.next = None  # Remove the last node by setting the next pointer of the second-last node to None

Il metodo sopra verifica innanzitutto se la lista collegata è vuota, restituendo un messaggio all’utente in tal caso. Altrimenti, se la lista contiene un solo nodo, quel nodo viene rimosso. Per liste con più nodi, il metodo individua il penultimo nodo e aggiorna il riferimento al suo nodo successivo a None.

Aggiorniamo ora la funzione main per eliminare elementi dall’inizio e dalla fine della lista collegata:

if __name__ == '__main__':
    llist = LinkedList()

    # Insert words at the beginning
    llist.insertAtBeginning('fox')
    llist.insertAtBeginning('brown')
    llist.insertAtBeginning('quick')
    llist.insertAtBeginning('the')

    # Insert a word at the end
    llist.insertAtEnd('jumps')

    # Print the list before deletion
    print("List before deletion:")
    llist.printList()

    # Deleting nodes from the beginning and end
    llist.deleteFromBeginning()
    llist.deleteFromEnd()

    # Print the list after deletion
    print("List after deletion:")
    llist.printList()

Il codice sopra stamperà la lista prima e dopo le eliminazioni, mostrando come funzionano le operazioni di inserimento ed eliminazione nelle liste collegate. Dovresti vedere il seguente output dopo l’esecuzione:

List before deletion:
the quick brown fox jumps 
List after deletion:
quick brown fox

Cercare un valore specifico nella lista collegata

L’ultima operazione che impareremo in questo capitolo è il recupero di un valore specifico nella lista collegata. Per farlo, il metodo dovrebbe partire dalla testa della lista e iterare attraverso ogni nodo, verificando se i dati del nodo corrispondono al valore cercato. Ecco un’implementazione pratica di questa operazione:

def search(self, value):
    current = self.head  # Start with the head of the list
    position = 0  # Counter to keep track of the position
    while current: # Traverse the list
        if current.data == value: # Compare the list's data to the search value
            return f"Value '{value}' found at position {position}" # Print the value if a match is found
        current = current.next
        position += 1
    return f"Value '{value}' not found in the list" 

Per trovare valori specifici nella lista collegata che abbiamo creato, aggiorna la tua funzione main includendo il metodo di ricerca che abbiamo appena scritto:

if __name__ == '__main__':
    llist = LinkedList()

    # Insert words at the beginning
    llist.insertAtBeginning('fox')
    llist.insertAtBeginning('brown')
    llist.insertAtBeginning('quick')
    llist.insertAtBeginning('the')

    # Insert a word at the end
    llist.insertAtEnd('jumps')

   # Print the list before deletion
    print("List before deletion:")
    llist.printList()

    # Deleting nodes from beginning and end
    llist.deleteFromBeginning()
    llist.deleteFromEnd()

    # Print the list after deletion
    print("List after deletion:")
    llist.printList()
    
        # Search for 'quick' and 'lazy' in the list
    print(llist.search('quick'))  # Expected to find
    print(llist.search('lazy'))   # Expected not to find

Il codice sopra produrrà il seguente output:

List before deletion:
the quick brown fox jumps 
List after deletion:
quick brown fox 
Value 'quick' found at position 0
Value 'lazy' not found in the list

La parola “quick” è stata trovata con successo nella lista collegata poiché esiste in prima posizione. Tuttavia, la parola “lazy” non fa parte della lista, motivo per cui non è stata trovata.

Considerazioni finali

Se sei arrivato fin qui, complimenti! Ora hai una solida comprensione dei principi di base delle liste collegate, inclusa la loro struttura, i tipi, come aggiungere e rimuovere elementi e come attraversarle.

Ma il viaggio non finisce qui. Le liste collegate sono solo l’inizio del mondo delle strutture dati e degli algoritmi. Ecco alcuni possibili prossimi passi per approfondire l’argomento:

Crea un tuo progetto

Immergiti nelle applicazioni pratiche delle liste collegate integrandole in un progetto di coding o di data science. Le liste collegate vengono usate per sviluppare file system, costruire hash table e persino creare sistemi di navigazione GPS e giochi da tavolo. Per iniziare con i tuoi progetti, dai un’occhiata ai nostri progetti di data science guidati e gratuiti che ti insegnano a risolvere problemi reali in Python, R e SQL.

Impara strutture dati e algoritmi

Imparare altre strutture dati, come alberi, stack e code, è una naturale evoluzione della comprensione delle liste collegate. Queste strutture si basano sui principi delle liste collegate, aiutandoti a risolvere in modo efficiente una gamma più ampia di problemi computazionali. Gli alberi e i binary search tree, ad esempio, estendono il concetto di liste collegate in una forma gerarchica, consentendo a ogni nodo di connettersi a più elementi nella struttura dati.

Se questi concetti ti suonano poco familiari, niente panico! Datacamp ha un intero corso su strutture dati e algoritmi in Python che ti guiderà in questi concetti in maggior dettaglio. Per prima cosa imparerai strutture dati come stack, alberi, tabelle hash, code e grafi. Progredendo nel corso, acquisirai comprensione di algoritmi di ricerca e ordinamento, che ti aiuteranno a diventare un programmatore e un problem-solver più efficiente.

Esplorare concetti avanzati di liste collegate

In questo tutorial abbiamo implementato liste semplicemente collegate, coprendo operazioni come inserimento, eliminazione e traversata.

Puoi fare un passo oltre imparando l’implementazione di liste doppiamente collegate e circolari. Le skip list sono un’altra estensione delle liste collegate che consentono ricerche più veloci facilitando un accesso più rapido agli elementi.

Imparare queste strutture dati avanzate porterà le tue competenze tecniche al livello successivo e migliorerà notevolmente le tue capacità di programmazione, preparandoti a sfide più complesse in ambiti come data science, sviluppo software e machine learning engineering.

Se desideri un’introduzione più adatta ai principianti alla programmazione prima di affrontare questi argomenti avanzati, esplora il nostro percorso di competenze Python Programming. Offre una serie di corsi che ti insegneranno le basi del linguaggio.


Natassha Selvaraj's photo
Author
Natassha Selvaraj

Natassha è una consulente data che lavora all'intersezione tra data science e marketing. Crede che i dati, se usati con intelligenza, possano ispirare una crescita straordinaria per persone e organizzazioni. Come professionista dei dati autodidatta, Natassha ama scrivere articoli che aiutino altri aspiranti data scientist a entrare nel settore. I suoi articoli, pubblicati sul suo blog personale e su testate esterne, registrano in media 200.000 visualizzazioni mensili.

Argomenti

Continua a imparare Python!

Programma

Fondamenti di dati in Python

28 h
Accresci le tue competenze sui dati, scopri come manipolarli e visualizzarli e applica analisi avanzate per prendere decisioni basate sui dati.
Vedi dettagli
Inizia Il Corso
Mostra altro
Correlato

blog

Tokenizzazione nel NLP: come funziona, sfide e casi d'uso

Guida al preprocessing NLP nel machine learning. Copriamo spaCy, i transformer di Hugging Face e come funziona la tokenizzazione in casi d'uso reali.
Abid Ali Awan's photo

Abid Ali Awan

10 min

blog

Che cos'è Snowflake? Guida per principianti alla piattaforma dati cloud

Esplora le basi di Snowflake, la piattaforma dati cloud. Scopri la sua architettura, le sue funzionalità e come integrarla nelle tue pipeline di dati.
Tim Lu's photo

Tim Lu

12 min

blog

I 15 migliori server MCP remoti che ogni AI builder dovrebbe conoscere nel 2026

Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Abid Ali Awan's photo

Abid Ali Awan

15 min

Mostra AltroMostra Altro
Morty Proxy This is a proxified and sanitized view of the page, visit original site.