STRUTTURA DATI: LISTA SEMPLICE
La Lista Semplice è una struttura dati dinamica composta da nodi
collegati tra loro.
A differenza degli array, non ha una dimensione fissa e permette di
inserire o rimuovere elementi senza dover ridimensionare l’intera
struttura.
L’accesso agli elementi, però, è sequenziale, poiché non esiste un
indice diretto.
STRUTTURA INTERNA
Ogni nodo della lista è composto da due campi:
data: il valore contenuto nel nodo.next: riferimento al nodo successivo (oppurenullse è l’ultimo).
La lista è gestita tramite un puntatore alla testa (head), che rappresenta il primo nodo e consente di accedere all’intera struttura.
PROBLEMA DELLA “FRAGILITÀ DELLA TESTA”
Durante l’iterazione della lista, se si utilizza direttamente la testa, il riferimento al primo nodo può essere perso.
Esempio:
- Lista iniziale:
2 → 5 - Testa:
2
Se scorro la lista senza usare una copia, la testa può diventare null,
perdendo l’accesso alla struttura.
Soluzione: usare una copia della testa per iterare, così il riferimento originale alla lista rimane intatto.
OPERAZIONI PRINCIPALI
inserisciInTesta(valore)→ inserisce un nodo in testa alla lista.inserisciInCoda(valore)→ inserisce un nodo in fondo alla lista.rimuovi(valore)→ rimuove il primo nodo con valore uguale a quello dato.cerca(valore)→ restituisce il primo nodo che contiene il valore dato.stampaLista()→ stampa tutti i valori partendo dalla testa.
PRESTAZIONI
- Inserimento in testa → O(1)
- Rimozione in testa → O(1)
- Inserimento in coda → O(n) (se non si mantiene un puntatore alla coda)
- Ricerca di un elemento → O(n)
- Accesso diretto ad una posizione → O(n)
NOTE
- Struttura semplice ed efficiente per inserimenti/rimozioni in testa.
- Poco adatta per accessi casuali (serve scorrere sequenzialmente).
- È la base per strutture più complesse come liste doppiamente collegate o liste circolari. */
CODICE
// Nodo generico
class ListNode<E> {
data: E;
next: ListNode<E> | null = null;
/**
* Costruttore del nodo
* @param data valore del nodo
*/
constructor(data: E) {
this.data = data;
this.next = null;
}
}
class LinkedList<E> {
private head: ListNode<E> | null;
/**
* Costruttore della lista, col puntatore al primo elmento della lista
* @param head nodo che farà da testa alla lista
*/
constructor(head: ListNode<E> | null) {
this.head = head;
}
/**
* Calcola il numero di elementi della lista
* @returns numero di elementi della lista
*/
size(): number {
let count = 0;
let node = this.head;
while (node) {
count++;
node = node.next;
}
return count;
}
/**
* Si posizione alla fine della lista e ritorna l'ultimo elmento
* @returns ultimo nodo della lista
*/
getLast(): ListNode<E> | null {
let node = this.head;
if (!node) return null;
while (node.next) {
node = node.next;
}
return node;
}
/**
* Funzione che aggiunge un nuovo nodo alla fine
* @param newNode nodo che deve inserito
*/
add(newNode: ListNode<E>): void {
if (!this.head) {
this.head = newNode;
} else {
const last = this.getLast();
if (last) {
last.next = newNode;
}
}
}
/**
* Funzione che rimuove tutti i nodi che hanno come valore lo stesso v passato in input
* @param v valore dei nodi da cancellare all'interno della funzione
*/
remove(v: E): void {
const dummy = new ListNode<E>(null as any); // dummy head
dummy.next = this.head;
let curr = dummy;
while (curr.next) {
if (curr.next.data === v) {
curr.next = curr.next.next;
} else {
curr = curr.next;
}
}
this.head = dummy.next;
}
/**
* Restituisce il valore della cella della lista alla posizione pos
* @param pos posizione da verificare il valore
* @returns valore alla posizione data in input
*/
at(pos: number): E | null {
let curr = this.head;
let i = 0;
while (curr) {
if (i === pos) return curr.data;
curr = curr.next;
i++;
}
return null;
}
/**
* Restituisce la lista come stringa
* @returns stringa che rappresenta la stringa
*/
toString(): string {
if (!this.head) return "vuota";
let result = "";
let curr = this.head;
while (curr) {
result += curr.data + (curr.next ? " -> " : "");
curr = curr.next!;
}
return result;
}
/**
* Stampa la lista
*/
print(): void {
console.log(this.toString());
}
}
// Test
const node1 = new ListNode<number>(7);
const node2 = new ListNode<number>(5);
const list = new LinkedList<number>(node1);
list.add(node2);
console.log("elemento in posizione 0:", list.at(0));
console.log("grandezza della lista:", list.size());
list.print();
list.remove(7);
list.print();