TextFile
liste concatenate Le liste concatenate sono una delle strutture dati fondamentali per ogni programmatore C. Sebbene richiedano una buona comprensione dei puntatori e della gestione dinamica della memoria, offrono una flessibilità che gli array non possono garantire.
home page
 

Liste concatenate in C

Pubblicato il: 3-7-2026

Ultima Modifica: 3-7-2026

Le liste concatenate nel linguaggio C spiegate ai principianti

Le liste concatenate (Linked List) rappresentano una delle strutture dati più importanti del linguaggio C. Anche se all'inizio possono sembrare complicate, una volta compreso il loro funzionamento diventano uno strumento estremamente potente.

📚 In questo articolo vedremo:

  • Cosa sono le liste concatenate

  • Perché utilizzarle

  • Come creare un nodo

  • Inserire elementi

  • Scorrere la lista

  • Eliminare elementi

  • Liberare la memoria

  • Esempio completo commentato


📌 Cosa sono le liste concatenate?

Una lista concatenata è una collezione di elementi chiamati nodi.

Ogni nodo contiene due informazioni:

  • un dato

  • il puntatore al nodo successivo

Immaginiamo questa situazione:

+-------+      +-------+      +-------+
|  10   | ---> |  25   | ---> |  80   | ---> NULL
+-------+      +-------+      +-------+

Ogni casella è un nodo.

L'ultimo nodo punta a NULL, indicando la fine della lista.


💡 Perché usare una lista concatenata?

Con gli array bisogna conoscere prima la dimensione.

Ad esempio:

  
int numeri[100];

Se servono 101 elementi?

Bisogna ricreare l'array.

Con una lista concatenata, invece:

✅ cresce quando serve

✅ occupa solo la memoria necessaria

✅ permette inserimenti veloci


🧱 La struttura di un nodo

In C si utilizza una struttura.

 
struct Nodo
{
    int valore;
    struct Nodo *successivo;
};

Spieghiamola.

int valore;

Contiene il numero.

struct Nodo *successivo;

È il puntatore al nodo seguente.


🎨 Rappresentazione grafica

+---------------------+
| valore = 15         |
| successivo ---------|------>
+---------------------+

Ogni nodo conosce solamente quello successivo.


🔨 Creare un nodo

Per creare un nodo serve memoria dinamica.

  
#include <stdlib.h>

struct Nodo *nuovo;

nuovo = malloc(sizeof(struct Nodo));

Adesso il nodo esiste.

Possiamo riempirlo.

  
nuovo->valore = 20;
nuovo->successivo = NULL;

Il simbolo -> serve per accedere ai membri di una struttura puntata.


📌 Cos'è la testa della lista?

Il primo elemento viene chiamato Head (testa).

Head
 |
 V

+-----+     +-----+     +-----+
| 10  | --> | 30  | --> | 80  |
+-----+     +-----+     +-----+

La testa permette di raggiungere tutti gli altri nodi.


➕ Inserire il primo nodo

 
struct Nodo *head = NULL;

head = malloc(sizeof(struct Nodo));

head->valore = 50;
head->successivo = NULL;

La lista contiene un solo elemento.


➕ Inserire un secondo nodo

Creiamo un nuovo nodo.

  
struct Nodo *nuovo;

nuovo = malloc(sizeof(struct Nodo));

nuovo->valore = 100;
nuovo->successivo = NULL;

Ora colleghiamo il primo al secondo.

  
head->successivo = nuovo;

La lista diventa:

50 ---> 100 ---> NULL

🔄 Scorrere la lista

Per leggere tutti gli elementi si usa un puntatore temporaneo.

  
struct Nodo *corrente;

corrente = head;

Finché non arriva a NULL.

  
while(corrente != NULL)
{
    printf("%d\n", corrente->valore);

    corrente = corrente->successivo;
}

Output

50
100

🎯 Inserire sempre in testa

Molto semplice.

Nuovo nodo

     |
     V

20 ---> 50 ---> 100

Codice:

  
struct Nodo *nuovo;

nuovo = malloc(sizeof(struct Nodo));

nuovo->valore = 20;

nuovo->successivo = head;

head = nuovo;

Il nuovo nodo diventa il primo.


➕ Inserimento in coda

Bisogna raggiungere l'ultimo nodo.

  
struct Nodo *corrente;

corrente = head;

while(corrente->successivo != NULL)
{
    corrente = corrente->successivo;
}

corrente->successivo = nuovo;

🔎 Cercare un valore

Supponiamo di voler trovare il numero 80.

  
struct Nodo *corrente;

corrente = head;

while(corrente != NULL)
{
    if(corrente->valore == 80)
    {
        printf("Trovato!\n");
        break;
    }

    corrente = corrente->successivo;
}

❌ Eliminare il primo nodo

È l'operazione più semplice.

  
struct Nodo *temp;

temp = head;

head = head->successivo;

free(temp);

Il primo nodo viene eliminato.


❌ Eliminare un nodo interno

Supponiamo di voler eliminare il valore 30.

10 --> 30 --> 70

diventa

10 --------> 70

Bisogna far puntare il nodo precedente direttamente al successivo.


🧹 Liberare tutta la memoria

Molti principianti dimenticano questa parte.

È importantissima.

  
struct Nodo *corrente;
struct Nodo *temp;

corrente = head;

while(corrente != NULL)
{
    temp = corrente;

    corrente = corrente->successivo;

    free(temp);
}

Così non rimangono perdite di memoria (Memory Leak).


⚠️ Errori comuni

Dimenticare malloc()

  
struct Nodo *n;

n->valore = 5;

Errore!

Il puntatore non punta a memoria valida.


Dimenticare NULL

 
nuovo->successivo = NULL;

Se manca questa istruzione, il programma potrebbe leggere memoria casuale.


Dimenticare free()

Ogni malloc() dovrebbe avere il suo free().

Altrimenti la memoria rimane occupata.


🧠 Differenza tra array e lista

Array Lista concatenata
Dimensione fissa Dimensione dinamica
Accesso molto veloce Accesso sequenziale
Inserimento lento Inserimento veloce
Occupa memoria continua Memoria sparsa

📦 Esempio completo

 
#include <stdio.h>
#include <stdlib.h>

struct Nodo
{
    int valore;
    struct Nodo *successivo;
};

int main()
{
    struct Nodo *head = NULL;
    struct Nodo *n1;
    struct Nodo *n2;
    struct Nodo *corrente;

    n1 = malloc(sizeof(struct Nodo));
    n2 = malloc(sizeof(struct Nodo));

    n1->valore = 10;
    n1->successivo = n2;

    n2->valore = 50;
    n2->successivo = NULL;

    head = n1;

    corrente = head;

    while(corrente != NULL)
    {
        printf("%d\n", corrente->valore);

        corrente = corrente->successivo;
    }

    free(n1);
    free(n2);

    return 0;
}

Output:

10
50

🚀 Vantaggi delle liste concatenate

✔ Crescono dinamicamente.

✔ Inserimento molto rapido.

✔ Eliminazione veloce.

✔ Ideali quando il numero di elementi non è noto in anticipo.

✔ Molto utilizzate nei sistemi operativi, nei compilatori, nei database e in numerosi algoritmi.


📖 Conclusione

Le liste concatenate sono una delle strutture dati fondamentali per ogni programmatore C. Sebbene richiedano una buona comprensione dei puntatori e della gestione dinamica della memoria, offrono una flessibilità che gli array non possono garantire.

Una volta acquisiti questi concetti, sarà più semplice affrontare strutture dati ancora più evolute, come le liste doppiamente concatenate, le liste circolari, le pile (stack), le code (queue) e gli alberi binari, tutte basate sugli stessi principi.

💡 Consiglio finale: prova a modificare gli esempi proposti aggiungendo funzioni per inserire, cercare ed eliminare nodi. La pratica è il modo migliore per padroneggiare questa importante struttura dati e prepararti ad affrontare progetti di programmazione sempre più complessi.