Lezione n°6 Prof.ssa Rossella Petreschi Lezione del 22 /10/2014 del Corso di Algoritmica
Alberi autoaggiustanti Un albero bilanciato mantiene esplicitamente una condizione di bilanciamento sui nodi in modo da ottenere un tempo di esecuzione logaritmico nel caso peggiore per tutte le operazioni. Un albero auto-aggiustante garantisce tempo di esecuzione AMMORTIZZATO logaritmico su una sequenza di operazioni senza mantenere alcuna condizione esplicita di bilanciamento 2
MOVE TO ROOT Chiamiamo u o la chiave trovata durante una operazione di ricerca o l’elemento inserito durante una operazione di inserimento o il padre dell’elemento eliminato con una operazione di cancellazione L’idea alla base della trasformazione di un generico albero binario di ricerca in un albero auto-aggiustante, consiste nel portare u alla radice tramite successive rotazione semplice (o destra o sinistra). Ogni rotazione fa salire u di un livello verso la radice, pertanto il tempo richiesto é pari all’altezza dell’albero. In questo modo, però, non è garantita l’altezza ammortizzata logaritmica. 3
L’operazione di SPLAY Operazione splay(u): consiste nel partire da u e risalire alla radice dell’albero tramite una sequenza di rotazioni ciascuna delle quali fa salire u di due livelli verso la radice. A meno di simmetrie, queste le rotazioni: se u è fs di p(u) e p(u) è fs di p(p(u)) allora u prende il posto di p(p(u)) con fd p(u) che a sua volta ha p(p(u)) come fd (doppia rotazione destra) se u è fd di p(u) e p(u) è fs di p(p(u)) allora u prende il posto di p(p(u)) che diviene suo fd mentre p(u) diviene suo fs (rotazione destra/sinistra) 4
PER ARRIVARE ALLA RADICE Le rotazioni a. e/o b. si ripetono in sequenza finché è possibile. Poiché ogni rotazione fa salire u di due livelli, al termine della sequenza o u è la radice dell’albero o u è uno dei figli della radice. In quest’ultimo caso, bisogna effettuare un’ultima rotazione, la c., affinché u diventi radice: se p(u) = r e u è fs, u diviene nuova radice e r fd (rotazione destra) Ovviamente dopo ogni rotazione si debbono mantenere le proprietà di un albero di ricerca. 5
L’euristica Per rendere un albero binario di ricerca uno splay-tree, si itera splay(u) in corrispondenza di ogni operazione di accesso o di modifica dell’albero. Quindi u inizialmente sarà: chiave trovata o foglia su cui ci si ferma (operazione di ricerca) elemento inserito (operazione di inserimento) padre dell’elemento v eliminato (operazione di cancellazione) L’euristica prosegue fino alla radice e pertanto in ogni caso è proporzionale alla lunghezza del cammino su cui lo splay procede 6
La funzione potenziale (T) = r(x) = log size(x), per ogni x nello splay tree. Il valore del potenziale è tanto più piccolo quanto più l’albero è bilanciato (T)= log5+ log3+ 3log1≈ 3.9 (T)= log5+ log4+ …+log1≈ 5.9 7
Analisi ammortizzata su splay tree Il tempo totale ammortizzato di una sequenza di operazioni (di ricerca, di inserimento e di cancellazione) su uno splay-tree è data da ( logn), con n massimo numero di nodi che l’albero raggiunge durante la sequenza. Il tempo ammortizzato di una singola operazione di splay è pari (logm), con m numero di nodi dell’albero su cui si effettua l’operazione. 8
Analisi ammortizzata di un singolo passo di splay u fs di p(u) e p(u) fs di p(p(u)) (rotazione a.) i=ci+(Ti)-(Ti-1)= = 2+ri(u)+ri(p(u))+ri(p(p(u)))-ri-1(u)-ri-1(p(u))-ri-1(p(p(u)))= per (1,2) = 2+ri(p(u)) +ri(p(p(u)))-ri-1(u)-ri-1(p(u)) ≤ per (3) ≤ 2+ri(u) +ri(p(p(u)))-2ri-1(u)≤ per (4) ≤ [2+ri(u) +ri(p(p(u)))-2ri-1(u)] + [2 ri(u) - ri-1(u) - ri(p(p(u)))-2 ]=per (5) = 3[ri(u) - ri-1(u)] u,p(u),p(p(u)) sono gli unici nodi che cambiano il valore di size prima e dopo l’operazione di splay; ci misura il numero di rotazioni; sizei(u)= sizei-1(p(p(u))); ri-1(p(u)) ≥ ri-1(u); ri(p(u)) ≤ ri(u); 2 ri(u) - ri-1(u) - ri(p(p(u)))-2 ≥ 0 (in modo analogo u fs di p(u) e p(u) fd di p(p(u)) ) 9
Analisi ammortizzata di un singolo passo di splay 2 ri(u) - ri-1(u) - ri(p(p(u)))-2 ≥ 0 Per = sizei-1(u) / sizei(u) > 0; = sizei(p(p(u))) / sizei(u) >0; si ha +≤ 1 e quindi, per il lemma, log + log ≤ -2 Allora: log (sizei-1(u) / sizei(u)) + log (sizei(p(p(u))) / sizei(u)) ≤ -2 ri-1(u) + ri(p(p(u))) - 2ri(u) ≤ -2 ovvero 2ri(u) - ri-1(u) - ri(p(p(u))) - 2 ≥ 0 Lemma Datiereali positivi con +≤ 1, vale log + log ≤ -2 Prova: log + log = log la funzione logaritmo è monotona crescente e raggiunge il massimo, nell’intervallo dell’ipotesi, quando è massimo ovvero quando ovvero log + log = -2 10
Analisi ammortizzata di un singolo passo di splay u fs di p(u) e r = p(u) (rotazione c.) i= ci+(Ti)-(Ti-1)= per (1,2) = 1+ri(u)+ri(p(u)) -ri-1(u)-ri-1(p(u)) = per (3) = 1+ri(u)+ri(p(u)) -ri-1(u)- ri(u) = = 1+ ri(p(u)) -ri-1(u)≤ ≤ 1+ri(u) -ri-1(u) ≤ ≤ 1 + 3[ri(u) - ri-1(u)] u,p(u) sono gli unici nodi che cambiano il valore di size prima e dopo l’operazione di splay; ci misura il numero di rotazioni; ri-1(p(u)) = ri(u) La dimostrazione relativa alla rotazione b. è analoga a quella relativa alla rotazione a. 11
Complessità ammortizzata totale Il tempo ammortizzato di una singola operazione di splay è pari a (logm), con m numero dei nodi dell’albero in cui si effettua l’operazione, dato che: i + k+1 ≤ 3(ri(u) - ri-1(u)) + 1 + 3 (rk+1(u) – rk(u)) = , per i= 1,…k 1 + 3 (rangofinale(u) - riniziale(u)) ≤ 1+ 3log m dato che rangoiniziale(u) = 0 e rangofinale(u) ≤ log m Il tempo totale ammortizzato di una sequenza di operazioni (di ricerca, di inserimento e di cancellazione) su uno splay-tree è data da ( logn), con n massimo numero di nodi che l’albero raggiunge durante la serie di operazioni. 12
Applicazioni Gli splay tree sono stati pensati per l'implementazione di cache dove gli algoritmi di gestione dei dati sono legati a due concetti fondamentali: località del codice: non si accede alle informazioni in modo uniforme (accesso casuale), ma ci sono parti di informazione a cui si accede più frequentementente (accesso localizzato). eliminazione dalla cache dei dati usati meno recentemente. Ad ogni accesso l'algoritmo splay sposta il nodo su cui opera alla radice,conseguentemente gli elementi a cui si accede più frequentemente si trovano sempre vicino alla radice dell'albero, rendendoli più velocemente accessibili e migliorando sensibilmente i tempi di accesso globali alla cache nelle operazioni di ricerca e cancellazione. 13