Alberi binari di ricerca Ilaria Castelli castelli@dii.unisi.it Università degli Studi di Siena Dipartimento di Ingegneria dell Informazione A.A. 2009/20010 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 1/39
Alberi binari di ricerca Definizione Visita dell albero Ricerca Ricerca minimo, massimo, successore Inserimento Ribilanciamento Rimozione I. Castelli Alberi binari di ricerca, A.A. 2009/20010 2/39
Alberi binari Remarks: Un albero binario si può rappresentare con una lista concatenata in cui ogni nodo rappresenta un oggetto x, costituito dai seguenti campi: key[x] p[x] left[x] right[x] Se un figlio, oppure il padre è mancante, il corrispondente puntatore contiene nil I. Castelli Alberi binari di ricerca, A.A. 2009/20010 3/39
Alberi binari di ricerca Un albero binario di ricerca è un albero binario con le seguenti caratteristiche: nei suoi nodi sono allocati gli elementi di un insieme A, su cui è definito un ordinamento totale se y è un nodo appartenente al sottoalbero sinistro di x, allora key[y] key[x] se y è un nodo appartenente al sottoalbero destro di x, allora key[y] key[x] Tutti gli elementi allocati nel sottoalbero sinistro di x precedono nell ordinamento l elemento allocato in x Tutti gli elementi allocati nel sottoalbero destro di x seguono nell ordinamento l elelemnto allocato in x I. Castelli Alberi binari di ricerca, A.A. 2009/20010 4/39
Alberi binari di ricerca 5 x 2 3 7 3 y1 y2 2 4 8 x 5 key[y1] <= key[x] key[y2] >= key[x] y1 4 7 y2 8 Sono entrambi alberi binari di ricerca, ma... qual è più efficiente? I. Castelli Alberi binari di ricerca, A.A. 2009/20010 5/39
Visita Inorder INORDER TREE WALK( x ) i f x!= NIL then INORDER TREE WALK( l e f t [ x ] ) p r i n t key [ x ] INORDER TREE WALK( r i g h t [ x ] ) È un algoritmo ricorsivo! Richiede tempo Θ(n) in un albero di n nodi L algoritmo stampa in ordine crescente le chiavi del sottoalbero che ha come radice il nodo x = È un algoritmo di ordinamento. Infatti vengono stampate nell ordine: le chiavi del sottoalbero sinistro di x la chiave di x le chiavi del sottoalbero destro di x I. Castelli Alberi binari di ricerca, A.A. 2009/20010 6/39
Visita Inorder root[t1] 5 root[t2] 2 3 7 3 2 4 8 5 2-3-4-5-7-8 4 7 8 2-3-4-5-7-8 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 7/39
Visita in ordine anticipato e posticipato ORDINE ANTICIPATO( x ) i f x!= NIL then p r i n t key [ x ] ORDINE ANTICIPATO( l e f t [ x ] ) ORDINE ANTICIPATO( r i g h t [ x ] ) Stampa nell ordine: la chiave di x le chiavi del sottoalbero sinistro di x le chiavi del sottoalbero destro di x ORDINE POSTICIPATO( x ) i f x!= NIL then ORDINE POSTICIPATO( l e f t [ x ] ) ORDINE POSTICIPATO( r i g h t [ x ] ) p r i n t key [ x ] Stampa nell ordine: le chiavi del sottoalbero sinistro di x le chiavi del sottoalbero destro di x la chiave di x I. Castelli Alberi binari di ricerca, A.A. 2009/20010 8/39
Visita in ordine anticipato e posticipato root[t1] 5 root[t2] 2 3 7 3 2 4 8 5 In Order: 2-3 - 4-5 - 7-8 Ordine Anticipato: 5-3 - 2-4 - 7-8 Ordine Posticipato: 2-4 - 3-8 - 7-5 4 7 8 In Order: 2-3 - 4-5 - 7-8 Ordine Anticipato: 2-3 - 5-4 - 7-8 Ordine Posticipato: 4-8 - 7-5 - 3-2 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 9/39
Ricerca TREE SEARCH( x, k ) i f x = NIL or k = key [ x ] then r e t u r n x i f k < key [ x ] then r e t u r n TREE SEARCH( l e f t [ x ], k ) e l s e r e t u r n TREE SEARCH( r i g h t [ x ], k ) Dati in ingresso il puntatore alla radice dell albero e una chiave, l algoritmo restituisce il nodo con chiave uguale a k, oppure NIL se non esiste. Sfruttando la proprietà di ordinamento dell albero binario di ricerca, l algoritmo discende l albero in modo ricorsivo. Non è necessario visitare tutti i nodi, ma solo O(h) I. Castelli Alberi binari di ricerca, A.A. 2009/20010 10/39
Ricerca Lo stesso algoritmo si può implementare usando un ciclo while, invece della ricorsione. TREE SEARCH 2( x, k ) w h i l e x!= NIL and k!= key [ x ] do i f k < key [ x ] then x = l e f t [ x ] e l s e x = r i g h t [ x ] r e t u r n x I. Castelli Alberi binari di ricerca, A.A. 2009/20010 11/39
Ricerca - Esempio 1 root[t] 9 5 15 4 7 12 16 2 6 8 11 13 19 1 3 18 21 key = 18 9-15-16-19-18 Trovato! I. Castelli Alberi binari di ricerca, A.A. 2009/20010 12/39
Ricerca - Esempio 2 root[t] 9 5 15 4 7 12 16 2 6 8 11 13 19 1 3 18 21 key = 10 9-15-12-11-N IL NON Trovato! I. Castelli Alberi binari di ricerca, A.A. 2009/20010 13/39
Ricerca del minimo TREE MINIMUM( x ) w h i l e l e f t [ x ]!= NIL do x = l e f t [ x ] r e t u r n x Si sfrutta la proprietà dell albero binario di ricerca. Partendo dal nodo x si ha che: Se x ha un figlio sinistro, allora il minimo è nel sottoalbero sinistro, poiché per ogni nodo y s in esso contenuto vale key[y s ] key[x] Se x non ha un figlio sinistro, allora per ogni nodo yd contenuto nel sottoalbero destro vale key[y d ] key[x]. Quindi, il minimo è x stesso I. Castelli Alberi binari di ricerca, A.A. 2009/20010 14/39
Ricerca del massimo TREE MAXIMUM( x ) w h i l e r i g h t [ x ]!= NIL do x = r i g h t [ x ] r e t u r n x Simmetrico rispetto al problema di ricerca del minimo. La complessità in tempo per la ricerca del minimo e del massimo è pari all altezza dell albero, ossia O(h) I. Castelli Alberi binari di ricerca, A.A. 2009/20010 15/39
Ricerca del minimo e del massimo - Esempio root[t] 9 5 15 4 7 12 16 2 6 8 11 13 19 1 3 18 21 Minimo: 9-5-4-2-1 Trovato! Massimo: 9-15-16-19-21 Trovato! I. Castelli Alberi binari di ricerca, A.A. 2009/20010 16/39
Ricerca del successore Il successore di un nodo x è definito come il nodo y con la più piccola chiave maggiore di key[x]: succ(key[x]) = min {y T : key[x] < key[y]} Supponiamo che nell albero T ci siano solo chiavi distinte Sfruttando le proprietà dell albero binario di ricerca si può trovare il successore di x senza dover confrontare le chiavi nei nodi I. Castelli Alberi binari di ricerca, A.A. 2009/20010 17/39
Ricerca del successore TREE SUCCESSOR( x ) i f r i g h t [ x ]!= NIL then r e t u r n TREE MINIMUM( r i g h t [ x ] ) y = p [ x ] w h i l e y!= NIL and x = r i g h t [ y ] do x = y y = p [ y ] r e t u r n y 1 Se il nodo ha un figlio destro il successore di x è il minimo del sottoalbero destro 2 Se il nodo non ha un figlio destro il successore di x è il più piccolo ascendente di x il cui figlio sinistro è anch esso un ascendente di x. In pratica: si risale l albero finché il nodo di provenienza sta a sinistra. Il nodo di partenza risulta essere il massimo del sottoalbero sinistro di y. Quindi y è il suo successore. I. Castelli Alberi binari di ricerca, A.A. 2009/20010 18/39
Ricerca del successore - caso 1 Se x ha un figlio destro, è sufficiente cercare il minimo del sottoalbero destro. <5 >5 root[t] 9 5 15 4 7 12 16 2 6 8 11 13 19 1 3 minimo del sottoalbero dx 18 21 Nodi visitati: 5-7 - 6 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 19/39
Ricerca del successore - caso 2 Se x non ha un figlio destro, si risale l albero fino a trovare la radice del sottoalbero di cui x è il massimo. root[t] 9 radice del sottoalbero di cui 8 e il massimo <8 >8 5 15 4 7 12 16 2 6 8 11 13 19 1 3 18 21 Nodi visitati: 8-7 - 5-9 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 20/39
Ricerca del successore - considerazioni Il tempo necessario per trovare il successore è pari a O(h), dove h è l altezza dell albero. Si percorre un cammino non più lungo della distanza massima tra la radice e una foglia. Predecessore Il predecessore di un nodo x è definito come il nodo y con la più grande chiave minore di key[x]: pred(key[x]) = max {y T : key[y] < key[x]} Per trovare il nodo predecessore si utilizza un algoritmo simmetrico: TREE-PREDECESSOR(x) (Esercizio) Anche TREE-PREDECESSOR(x) richiede tempo O(h), per motivi analoghi. I. Castelli Alberi binari di ricerca, A.A. 2009/20010 21/39
Inserimento e rimozione Inserendo o rimuovendo un elemento la struttura dell albero cambia L albero deve mantenere le proprietà di un albero binario di ricerca La struttura dell albero varia a seconda della sequenza di dati inseriti o rimossi L inserimento è un operazione semplice e immediata La rimozione è più complessa... I. Castelli Alberi binari di ricerca, A.A. 2009/20010 22/39
Inserimento 1 TREE INSERT (T, z ) 2 y = NIL / padre / 3 x = r o o t [T] / f i g l i o / 4 5 w h i l e x!= NIL / f i n c h e non s i r a g g i u n g e l a p o s i z i o n e 6 i n c u i i n s e r i r e z ( x = NIL ) / 7 y = x / memorizza i l nodo padre / 8 i f key [ z ] < key [ x ] / p r e n d i i l f i g l i o g i u s t o / 9 then x = l e f t [ x ] 0 e l s e x = r i g h t [ x ] 1 2 p [ z ] = y / i n s e r i s c i z come f i g l i o d i y / 3 i f y = NIL / s e l a l b e r o e vuoto / 4 then r o o t [T] = z / z d i v e n t a l a r a d i c e / 5 e l s e i f key [ z ] < key [ y ] / a l t r i m e n t i e un f i g l i o d i y / 6 then l e f t [ y ] = z 7 e l s e r i g h t [ y ] = z I. Castelli Alberi binari di ricerca, A.A. 2009/20010 23/39
Inserimento Si usano due puntatori x e y x scende lungo l albero alla ricerca della posizione in cui inserire z y punta al padre di x Nel ciclo while, x scende al figlio destro o sinistro a seconda dell esito del confronto tra key[z] e key[x] Si esce dal ciclo quando x = NIL: x occupa la posizione in cui z verrà inserito e quindi y punta al nodo che diventerà il padre di z Nelle linee 12-17 viene effettuato l inserimento Che costo ha l operazione di inserimento? Il tempo necessario è O(h): non più del cammino massimo tra la radice e una foglia I. Castelli Alberi binari di ricerca, A.A. 2009/20010 24/39
Inserimento - esempio 1 T REE INSERT (T, z) con key[z] = 14 root[t] 9 5 15 4 7 12 16 2 6 8 11 13 y 19 z 1 3 14 18 21 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 25/39
Inserimento - esempio 2 sequenza: 5-4 - 7-2 - 6-8 root[t] 5 root[t] 5 root[t] 5 4 4 7 root[t] 5 root[t] 5 root[t] 5 4 7 4 7 4 7 2 2 6 2 6 8 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 26/39
Inserimento - esempio 3 sequenza: 8-7 - 6-4 - 5-2 root[t] 8 6 7 La struttura dell albero risulta diversa a seconda della sequenza di inserimento! 4 2 5 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 27/39
Ribilanciamento Come ristrutturare l albero in modo che sia bilanciato? Supponiamo di partire da un albero bilanciato per = 1 Se l albero ottenuto dopo un inserimento risulta non bilanciato dobbiamo: individuare il nodo critico, cioè il nodo al livello massimo che viola il bilanciamento 16 16 6 30 6 30 2 9 20 37 2 9 20 37 3 7 13 22 33 40 3 7 13 22 33 40 ristrutturare il sottoalbero che ha come radice il nodo critico 25 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 28/39
Ribilanciamento - caso 1 ρ r Nodo critico s r s τ h h+1 k r < s σ < s σ > r z > s σ τ ρ σ z k+1 z 1 L albero ristrutturato ancora un albero binario di ricerca, poiché lo spostamento dei nodi r, s e dei sotto alberi ρ, σ e τ rispetta l ordinamento degli elementi allocati nell albero 2 Nella sezione dell albero che è stata alterata nessun nodo presenta sbilanciamento 3 Nella sezione dell albero che non è stata alterata nessun nodo può presentare sbilanciamento, poiché nella sezione alterata si è ripristinato il livello massimo k + 1 che era raggiunto nell albero originario prima dell inserimento di z k+2 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 29/39
Ribilanciamento - caso 2 r Nodo critico t s r t s h h+1 h+2 σ < t σ > r τ < s t > r ρ σ τ k σ τ ω ρ z ω k+1 z 1 L albero ristrutturato ancora un albero binario di ricerca, poiché lo spostamento dei nodi r, s, t e dei sotto alberi ρ, σ, τ e ω rispetta l ordinamento degli elementi allocati nell albero 2 Nella sezione dell albero che è stata alterata nessun nodo presenta sbilanciamento 3 Nella sezione dell albero che non è stata alterata nessun nodo può presentare sbilanciamento, poiché nella sezione alterata si è ripristinato il livello massimo k + 1 che era raggiunto nell albero originario prima dell inserimento di z k+2 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 30/39
Ribilanciamento - esempio 1 16 16 6 30 6 30 r 2 9 20 3 7 s 13 22 37 33 40 s 2 9 22 37 r z 3 7 13 20 25 33 40 z 25 ρ = σ = τ = I. Castelli Alberi binari di ricerca, A.A. 2009/20010 31/39
Ribilanciamento - esempio 2 8 r t 10 5 s 16 r 8 s 16 3 6 t 10 18 5 9 12 18 9 12 17 26 14 3 6 14 17 26 σ = {9} τ = {12} ρ =sottoalbero con radice 5 = {5, 3, 6} ω =sottoalbero con radice 18 = {18, 17, 26} I. Castelli Alberi binari di ricerca, A.A. 2009/20010 32/39
Ribilanciamento - considerazioni Poiché si può ribilanciare un albero binario di ricerca in tempo costante dopo l inserimento di un nuovo elemento, questa struttura permette di eseguire una qualsiasi sequenza di operazioni di inserzione e ricerca in modo efficiente. Il numero massimo di confronti tra elementi richiesto da tali operazioni coincide con h, l altezza dell albero. I. Castelli Alberi binari di ricerca, A.A. 2009/20010 33/39
Rimozione T REE DELET E(T, z) Ci sono tre casi: 1 Se z non ha figli, si modifica p[z] in modo che punti non più a z, ma a NIL 2 Se z ha un unico figlio, si taglia fuori z dall albero, facendo puntare p[z] all unico figlio di z 3 Se z ha due figli, si individua il suo successore, ossia il minimo del suo sottoalbero destro. Il successore y ha al più il figlio destro (perchè?). Quindi y prende il posto di z, e i dati in y vengono copiati nella posizione di z. I. Castelli Alberi binari di ricerca, A.A. 2009/20010 34/39
Rimozione - caso 1 z senza figli: key[z] = 14 9 5 15 4 7 12 16 2 6 8 11 13 19 1 3 z 14 18 21 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 35/39
Rimozione - caso 2 z con un figlio: key[z] = 16 9 5 15 4 7 12 z 16 2 6 8 11 13 19 1 3 14 18 21 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 36/39
Rimozione - caso 3 z con due figli: key[z] = 12 9 5 15 4 7 z 12 16 1 2 3 6 8 11 13 19 y successore di z: viene rimosso e va al posto di z 14 18 21 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 37/39
Rimozione - caso 3 z con due figli: key[z] = 12 9 5 15 4 7 y 13 16 2 6 8 11 14 19 1 3 12 18 21 I. Castelli Alberi binari di ricerca, A.A. 2009/20010 37/39
Rimozione 1 TREE DELETE(T, z ) 2 i f l e f t [ z ] = NIL or r i g h t [ z ] = NIL 3 then y = z / z ha 0 o 1 f i g l i o / 4 e l s e y = TREE SUCCESSOR( z ) / z ha 2 f i g l i, c e r c o succ ( z ) / 5 i f l e f t [ y ]!= NIL / x = f i g l i o non n u l l o d i y / 6 then x = l e f t [ y ] 7 e l s e x = r i g h t [ y ] / Nota : x puo d i v e n t a r e NIL / 8 9 i f x!= NIL / s e y ha un f i g l i o, t a g l i o f u o r i y / 0 then p [ x ] = p [ y ] 1 i f p [ y ] = NIL / s e y e r a l a r a d i c e / 2 then r o o t [T] = x / x d i v e n t a l a r a d i c e / 3 e l s e i f y = l e f t [ p [ y ] ] / a l t r i m e n t i x d i v e n t a f i g l i o 4 d e l padre d i y / 5 then l e f t [ p [ y ] ] = x 6 e l s e r i g h t [ p [ y ] ] = x 7 i f y!= z / s e i l nodo che ho t o l t o e s u c c ( z ) / 8 then key [ z ] = key [ y ] / c o p i o y a l p o s t o d i z / 9 // s e y ha anche a l t r i a t t r i b u t i c o p i a l i i n z 0 r e t u r n y I. Castelli Alberi binari di ricerca, A.A. 2009/20010 38/39
Rimozione - considerazioni Se siamo nel caso 1 oppure 2 l operazione di rimozione è immediata Se siamo nel caso 3 è necessario eseguire la procedura T REE SUCCESSOR(z), che ha una complessità temporale O(h) Quindi la rimozione richiede tempo O(h) Le operazioni di inserimento e di rimozione richiedono tempo O(h) I. Castelli Alberi binari di ricerca, A.A. 2009/20010 39/39