Problema: • Progettare strutture dati che supportino efficienti algoritmi di ricerca in insiemi dinamici, (ovvero in insiemi la cui composizione puó variare nel tempo (ad es., a causa di inserimenti di nuovi elementi, o cancellazioni di vecchi elementi, etc.) Operazioni di cui siamo interessati: • Interrogazioni: ritornano informazioni circa l’insieme S - S EARCH(S, k) - M INIMUM(S), M AXIMUM(S) - S UCCESSORE(S, x), P REDECESSORE(S, x) • Operazioni di modifica: cambiano la composizione dell’insieme S - I NSERT(S, x) - D ELETE(S, x) Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 1/20 Semplici strutture dati per il supporto delle operazioni • Array ordinato: - S EARCH(S, k) puó essere eseguita in tempo O(log n) - S UCCESSORE(S, x), P REDECESSORE(S, x) parimenti in tempo O(log n) - I NSERT(S, x), D ELETE(S, x) in tempo O(n) • Lista a puntatori: - S EARCH(S, k) viene eseguita in tempo O(n) - S UCCESSORE(S, x), P REDECESSORE(S, x) parimenti in tempo O(n) - I NSERT(S, x), D ELETE(S, x) in tempo O(1) Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 2/20 Alberi binari di ricerca • Supportano molte delle tipiche operazioni su insiemi dinamici: - S EARCH(S, k), S UCCESSORE(S, x), P REDECESSORE(S, x), I NSERT(S, x), D ELETE(S, x), M INIMO(S), M ASSIMO(S), ... • Il tempo di esecuzione di queste operazioni é O(h), dove h é l’altezza dell’albero binario di ricerca - nel caso peggiore: O(n) - nel caso medio: O(log n) Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 3/20 Ripasso di nozioni su alberi • Rappresentazione di alberi: - una struttura linkata in cui ciascun nodo é un oggetto • Rappresentazione di nodi: - campo chiave (contiene key[v]) - campo dati (contiene i dati satelliti) - Left: puntatore al figlio sinistro - Right: puntatore al figlio destro - Parent: puntatore al padre padre L R chiave figlio sinistro dati figlio destro Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 4/20 Alberi binari di Ricerca • Alberi binari con la proprietá addizionale: - se il nodo y é nel sottoalbero sinistro del nodo x allora key[y] ≤ key[x] - se il nodo y é nel sottoalbero destro del nodo x allora key[y] ≥ key[x] x ≤x ≥x Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 5/20 Esempi di alberi binari di ricerca 5 7 3 2 2 5 3 7 8 5 8 5 Dagli esempi si vede che differenti alberi di ricerca possono rappresentare lo stesso insieme. Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 6/20 Operazioni in alberi binari di ricerca: S EARCH(S, k) • Idea: partendo con u =radice dell’albero, confronta k con key[u], ricorsivamente cerca nel sottoalbero di sinistra di u se key[u] > k, nel sottoalbero di destra di u se key[u] < k, fin quando non trovi un nodo u con key[u] = k Tree-Search(x, k) %(x é il puntatore alla radice dell’albero) if x = NIL oppure k = key[x] then return (x) if k < key[x] then return (Tree-Search(Left[x], k)) else return (Tree-Search(Right[x], k)) Complessitá: O(h) , dove h é l’altezza dell’albero. Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 7/20 Esempio: ricerca di 13 15 6 7 3 2 18 17 20 13 4 9 Per cercare l’elemento 13 seguiamo il cammino 15 −→ 6 −→ 7 −→ 13, a partire dalla radice Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 8/20 Ricerca del Minimo in un albero binario di ricerca Tree-Minimum(x) while Left[x] 6= NIL x = Left[x] return (x) Complessitá: O(h) • Se un nodo x non ha sottoalbero sinistro, allora poiché ogni nodo nel sottoalbero di destra di x ha chiave ≥ key[x], ne segue che il minimo del sottoalbero radicato in x é proprio il nodo x. • Se un nodo x ha sottoalbero sinistro, allora poiché ogni nodo nel sottoalbero di destra di x ha chiave ≥ key[x] ed ogni nodo nel sottoalbero sinistro di x ha chiave ≤ key[x], ne segue che che il minimo del sottoalbero radicato in x si trova nel sottoalbero radicato nel figlio sinistro di x. Analoghe considerazioni varrano per la ricerca del Massimo (che si troverá o nella radice oppure nel sottoalbero di destra della stessa). Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 9/20 Ricerca del Successore e del Predecessore • Il successore di un elemento x é definito come quell’elemento y tale che esso ha la chiave key[y] di valore minimo, tra tutti gli elementi con chiavi di valore > key[x] 15 6 7 3 2 18 17 20 13 4 9 • Il successore di 15 é 17 • Il successore di 13 é 15 • Il successore di 9 é 13 Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 10/20 Ricerca del Successore: distinzione di casi 15 6 7 3 2 18 17 20 13 4 9 • Caso 1: Right(x) 6= NIL - il successore di x é l’elemento minimo nel sottoalbero destro di x (ad esempio, il successore di 15 é 17). • Caso 2: Right(x) = NIL - sali nell’albero fin quando non trovi un nodo y che é figlio sinistro: il successore di x é il padre di y. (ad esempio, il successore di 13 é 15, quello di 9 é 13) - Se non si puó salire ulteriormente (si é raggiunta la radice) allora x é il massimo (non ha successore) Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 11/20 Ricerca del Successore: Tree-Successor(x) if Right[x] 6= NIL then return (Tree-Minimum(Right[x])) y = Parent[x] while y 6= NIL and x = Right[y] x=y y = Parent[y] return (y) Complessitá: O(h) Considerazioni perfettamente analoghe varrano per la ricerca del Predecessore. Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 12/20 Inserzione di un nodo z in un albero binario di ricerca • Idea: Procedi come se volessi cercare z nell’albero - se key[x] > key[z] ricorri nel sottoalbero radicato in x = Left[x], altrimenti nel sottoalbero radicato in x = Right[x]. - quando x = NIL abbiamo trovato la posizione per z Esempio: inserzione di 7 15 6 18 3 2 8 4 7 17 20 13 Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 13/20 La procedura di inserzione Tree-Insert(T, z) y = NIL, x = root[T ] while x 6= NIL y=x if key[z] < key[x] then x = Left[x] else x = Right[x] Parent[z] = y if y = NIL then root[T ] = z else if key[z] < key[y] then Left[y] = z else Right[y] = z Esempio: inserzione di 7 15 6 18 3 2 8 4 7 17 13 Complessitá: O(h) Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 14/20 20 Cancellazione di un nodo z da un albero binario di ricerca • Idea: - Caso 1: z non ha figli • cancella z facendo puntare il padre di z a NIL invece che a z Esempio: cancellazione di 13 15 5 3 15 20 12 10 6 =⇒ 16 13 18 5 3 16 20 12 23 10 18 6 7 7 Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 15/20 23 Cancellazione di un nodo z da un albero binario di ricerca • Caso 2: z ha un solo figlio y - cancella z, facendo puntare il padre di z direttamente a y, indi aggiorna il puntatore al padre di y Esempio: cancellazione di 16 15 5 3 15 20 12 10 6 =⇒ 16 13 18 5 3 20 12 23 10 13 18 6 7 7 Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 16/20 23 Cancellazione di un nodo z da un albero binario di ricerca • Caso 3: z ha due figli - cancella z, sostituendolo con il nodo a lui piú simile, ovvero il successore (che per definizione ha al piú un figlio) Esempio: cancellazione di 5 15 5 3 15 20 12 10 6 5 16 13 18 3 16 20 12 23 10 13 18 6 7 7 Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 17/20 23 Cancellazione di un nodo z da un albero binario di ricerca Esempio: cancellazione di 5 L’albero risultante é 15 6 3 16 20 12 10 13 18 23 7 Complessitá: O(h) Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 18/20 Pseudocodice per cancellazione Tree-Delete(T, z) if Left[z] =NIL oppure Right[z] =NIL then y = z else y = Tree-Successor(z) if Left[y] 6= NIL then x = Left[y] else x = Right[y] if x 6= NIL then Parent[x] = Parent[y] if Parent[y] = NIL then root[T ] = x else if y = Left[Parent[y]] then Left[Parent[y]] = x else Right[Parent[y]] = x if y 6= z then key[z] = key[y] return (y) Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 19/20 Riassumendo: La struttura dati Albero Binario di ricerca supporta le operazioni di S EARCH(S, k), M INIMUM(S), M AXIMUM(S), S UCCESSORE(S, x), P REDECESSORE(S, x), I NSERT(S, x) e D ELETE(S, x) in tempo O(h), dove h é l’altezza dell’albero. Intuitivamente, l’albero sará “abbastanza” bilanciato (h ≈ log n) se si effettueranno le inserzioni e cancellazioni di elementi scelti a caso (ma non é detto che questa assunzione valga in pratica). Nel caso peggiore, l’altezza puó anche essere n, rendendo le operazioni sull’albero altamente inefficienti (ad es., se si inserissero gli elementi 1, 2, 3, . . . , n nell’ordine, l’albero binario di ricerca sarebbe equivalente ad una lista lunga n). Universitá degli Studi di Salerno – Corso di Introduzione agli Algoritmi e Strutture Dati – Prof. Ugo Vaccaro – Anno Acc. 2014/15 – p. 20/20