Presentazione di PowerPoint

annuncio pubblicitario
UNION FIND
Lezione n°8
Prof.ssa Rossella Petreschi
Lezione del 24 /10/ 2013 del Corso di Algoritmica
Union and find
La gestione dinamica ed efficiente di insiemi disgiunti (problematica
dello Union -Find) opera considerando una qualunque sequenza delle
seguenti tre operazioni:
• makesetx: creare un nuovo insieme x, di nome x, contenente un
nuovo elemento x;
• findx: dato un elemento x, restituire il nome dell’insieme che lo
contiene;
• unionA,B: dati due insiemi di nome A e B, costruire l’insieme
unione di nome A.
Notare che l’output dell’operazione union distrugge i due insiemi A e
B di input.
Alberi Quickfind
Un albero Quickfind è un albero di altezza 1che rappresenta un insieme i cui
elementi sono le foglie dell’albero. La radice contiene il nome dell’insieme.
Quindi, i costi delle tre operazioni base saranno:
• makesetx: O(1) perché richiede la creazione di un semplice albero con due
nodi;
• findx: O(1) perché è sufficiente restituire il nome del nodo radice, nodo
identificato dal puntatore dal nodo foglia x al nodo padre,radice;
• unionA,B: O(n) perché aggancia tutte le foglie di B ad A,quindi union
dipende dalla cardinalità di B che può essere dell’ordine di n, numero totale di
elementi in AB
L’occupazione totale di memoria della struttura dati è O(n) in qualunque istante
della sequenza delle operazioni.
Alberi Quickunion
Un albero Quickunion è un albero di altezza qualunque che rappresenta un
insieme i cui elementi sono i nodi dell’albero, radice compresa.
Quindi, i costi delle tre operazioni base saranno:
• makesetx: O(1) perché richiede la creazione di un semplice albero
composto da un solo nodo contenente x, che rappresenta sia il nome del nodo
che quello dell’albero;
• uniona,b: O(1) perché rende la radice dell’albero B (contenente il nodo b)
figlia della radice dell’albero A (contenente il nodo a);
• findx: O(n) perché restituisce la radice dell’albero contenente x.
L’occupazione totale di memoria della struttura dati è O(n) in qualunque
istante della sequenza delle operazioni.
Alberi Quickfind bilanciati
unionA,B: aggancia le foglie dell’albero di cardinalità minore alla radice
dell’albero di cardinalità maggiore. Nella radice sono memorizzati nome e
cardinalità dell’albero.
Siano Tp e Td i due alberi quickfind bilanciati a cui appartiene una foglia f
prima e dopo una operazione di union. La cardinalità dell’albero Td è almeno
il doppio della cardinalità dell’albero Tp. (size (A)+size(B) ≥ 2size(Tp))
O(m+nlogn) è il tempo totale necessario per eseguire su un albero quickfind
bilanciato una sequenza di:
m operazioni find,
n operazioni makeset,
al più (n-1)operazioni union.
perché O(m+nlogn)?
Un nuovo albero, x, creato in tempo O(1), ha cardinalità 1. Ogni volta che la foglia x
cambia padre, la dimensione dell’albero a cui appartiene per lo meno
raddoppia:2,4,8……, quindi dopo k cambi di “paternità”, x si troverà in un albero di
cardinalità almeno 2k.
Poiché dopo k cambi di “paternità”, al termine della sequenza di operazioni, x potrà
trovarsi in un albero di cardinalità al più n (n numero di makeset), ne segue che 2k ≤ n,
ovvero che una foglia può al più subire log2n cambiamenti.
Riassumendo:
le operazioni di find e di makeset hanno costo costante, m dell’una e n dell’altra
richiedono pertanto tempo 0(m+n). Le (n-1)operazioni union richiedono che al più tutte
le n foglie subiscano il massimo dei cambiamenti possibili, ovvero O(nlog2n), da cui una
sequenza di m operazioni find, n operazioni makeset e (n-1) operazioni union richiederà
un tempo dell’ordine O(m+n) + O(nlog2n) = O(m + nlog2n).
Alberi Quickunion bilanciati
unionA,B: rende la radice dell’albero più basso figlia della radice dell’albero
più alto.
La radice dell’albero risultante conterrà sia il nome del nuovo albero (p.e. A)
che la sua altezza (rank(A)).
Durante una sequenza di operazioni makeset, union e find, l’altezza di un
albero QuickUnion bilanciato è limitata superiormente da log2 n dove n è il
numero totale di makeset.
Prova:
Siano T un albero QuickUnion bilanciato di radice x e dimensione size(x) ≤ n.
Poiché size(x) ≥ 2rank(x) si ha che rank(x) ≤ log2n.
size(x) ≥ 2rank(x)
Si dimostra per induzione analizzando le differenti operazioni effettuate.
Makeset(x).: costruisce un albero di altezza 0 con rank(x) = 0 e non modifica nessun
albero preesistente, quindi : 2rank(x) = 20 =1.
Find(x).: non modifica nulla del preesistente.
Union(A,B).:
• Rank(B) < Rank(A), ovvero Rank(A∪B)= Rank(A) da cui
⎜A∪B⎜ = ⎜A⎜ + ⎜B⎜ ≥ 2 Rank(A) + 2 Rank(B) > 2 Rank(A) = 2 Rank(A∪B)
• Rank(A) < Rank(B) , ovvero Rank(A∪B)= Rank(B) da cui
⎜A∪B⎜ = ⎜A⎜ + ⎜B⎜ ≥ 2 Rank(A) + 2 Rank(B) > 2 Rank(B) = 2 Rank(A∪B)
• Rank(A) = Rank(B) , ovvero Rank(A∪B)= Rank(A) + 1 da cui
⎜A∪B⎜ = ⎜A⎜ + ⎜B⎜ ≥ 2 Rank(A) + 2 Rank(B) ≥ 2.2 Rank(A) = 2 Rank(A)+1 = 2 Rank(A∪B)
Tempo O(n + mlogn)
O(n+mlogn) è il tempo totale necessario per eseguire su un albero quickunion
bilanciato una sequenza di:
m operazioni find,
n operazioni makeset,
al più (n-1)operazioni union.
Deriva dal fatto che rank(x)≤logn
Sei differenti algoritmi
3 differenti euristiche di compressione
1. Path compression: rende tutti i nodi figli della radice
2. Path splitting: aggancia ogni nodo al proprio nonno
3. Path halving: aggancia solo i nodi di indice pari al proprio nonno
combinate con 2 differenti metodi di unione
a. Union by rank
b. Union by size
forniscono 6 differenti algoritmi: 1a, 1b, 2a, 2b, 3a, 3b
Analisi dell’algoritmo 1a
(Unione per ranghi compressi)
Con l’algoritmo 1a, una qualunque sequenza di n operazioni makeset, m
operazioni find e al più (n-1) operazioni union può essere realizzata in
tempo O(m+nlogn)
L’asserto verrà provato in modo ammortizzato assegnando un numero di crediti di (1+logn), 1 e 2
ad
ogni operazione di makeset,union e find, rispettivamente, da cui:
n(1+logn)+ (n-1) + 2m = O (m + nlogn).
Si deve mostrare che il numero di crediti assegnato è sufficiente per pagare il lavoro richiesto dalle
singole operazioni: sia  il cammino, che supponiamo di l nodi, visitato dalla find; i costi per la
visita della radice e del figlio della radice vengono pagati con i 2 crediti assegnati alla find, mentre
i
costi relativi ad ogni altro nodo x di p vengono pagati con i crediti che makeset immagazzina in x.
Resta da vedere se logn crediti di immagazzinamento siano sufficienti.
Notare che a causa della compressione dei cammini, ora rank non fornisce esattamente l’altezza,
ma una sua delimitazione superiore.
logn crediti di immagazzinamento sono sufficienti.
Una find richiede l’utilizzo di un credito immagazzinato in x quando
•
x non è né radice, né figlio della radice;
•
x sta acquistando come padre una nuova radice (path compression)
che avrà rank strettamente maggiore del vecchio padre di x (rank su
un cammino è una funzione monotona crescente)
Poiché rank ≤ logn, le operazioni di find non potranno richiedere a x di
utilizzare più di logn crediti
A proposito del rank
1. rank = 0
per ogni nuovo nodo creato da una operazione di makeset
2.
rank = rank + 1
dopo una union di due insiemi con radici dello stesso rank
e fintantoche x è radice
3.
rank(x) rimane invariato non appena x cessa di essere radice
4. rank(x)≤ rank(p(x))≤ logn e #nodi in T(x)=size(x) ≥ 2rank(x)
Quanti nodi hanno rank pari ad r?
Lemma: Durante l’esecuzione di una sequenza di makeset, union e find al più
n/2r nodi possono avere rank uguale ad r
Per la proprietà 2), quando si assegna rank(x) = r vuol dire che è stata appena
effettuata una operazione di union ed x è diventata radice di un qualche albero
con almeno 2r nodi (proprietà 4). Conseguentemente almeno 2r nodi saranno
etichettati x(r). Se x non sarà più radice, finirà in un albero di rank almeno r+1
(proprietà 2)
Visto che ci sono in totale n nodi ne segue che non sarà mai possibile avere più
di n/ 2r nodi di rank r
log*n e F(i)
log*n = min i (log(i)n )≤1
log(1)n = logn e …. log(i)n = log(log(i-1)n )= loglog….logn (i volte)
F (i) = 2F(i-1) se i ≥ 1; F(0) = 1
F(0) = 1
F(1) = 2
F(2) = 4
F(3) = 16
F(4) = 65536
F(5) = 265536
log*x = 0
log*x = 1
log*x = 2
log*x = 3
log*x = 4
log*x = 5
0<x≤1
1<x≤2
2<x≤4
4 < x ≤ 16
16 < x ≤ 65536
65536 < x ≤ 265536
Partizionamento dei nodi in blocchi
Come conseguenza del Lemma appena visto possiamo partizionare i nodi in blocchi nel
seguente modo: se un nodo v ha rank r, allora appartiene al blocco B(log*r).
Poichè rank ≤ logn, allora #blocchi ≤ log*(logn), da cui:
B(0) contiene nodi di rank in [0,1], ovvero [0,F(0)]
B(1) contiene nodi di rank in [2,2], ovvero [F(0) +1, F(1)]
B(2) contiene nodi di rank in [3,4], ovvero [F(1) +1, F(2)]
…………………………………
B(i) contiene nodi di rank in [F(i-1) +1, F(i)]
………………………
B(log*n-1) contiene nodi di rank in [F(log*n -2) +1, F(log*n-1)]
In ogni blocco ci saranno al più un numero di rank diversi ≤ F(i) - F(i-1) ≤ F(i)
Tempo O((n+m)log*n)
Raffiniamo l’assegnazione dei crediti: (1+log*n), 1 e (1+log*n), ad ogni
operazione di makeset, union e find, rispettivamente,da cui:
n(1+log*n) + (n-1) + m(1+log*n) = O((n+m) log*n)
Come nella prova precedente, sia  il cammino visitato dalla find (il cammino
si suppone di l nodi). I crediti assegnati alla find servono questa volta per
pagare i costi per la visita della radice, del figlio della radice e di tutti i nodi in
 che non sono nello stesso blocco del loro padre. I costi relativi ad ogni altro
nodo x di  (ovvero ad ogni altro nodo nello stesso blocco del padre) vengono
pagati con i crediti che makeset immagazzina in x.
Resta da vedere che i crediti così assegnati siano sufficienti.
I crediti assegnati alla find sono sufficienti
Poichè ci sono log*n blocchi distinti, per ogni find ci sono al più
log*n-1 nodi in un blocco diverso da quello del loro padre.
Quindi i crediti assegnati alla find sono sufficienti per soddisfare la
richiesta di log*n-1+2= log*n+1 nodi.
I crediti assegnati alla makeset sono sufficienti
Il numero di crediti immagazzinato dalle n operazioni makeset è sufficiente
perché si ha che:
1.
ogni nodo nel blocco richiede al più F(i) crediti;
2.
ci sono al più n/F(i) nodi nel blocco B(i) per 0 ≤ i ≤ log*n -1.
Prova di 1.
Ogni nodo in un generico blocco B(i) può chiedere al più F(i) crediti, dato che
ogni volta che richiederà un credito il rank di suo padre dovrà aumentare e nel
blocco B(i) ci sono al più F(i) - F(i-1) ≤ F(i) valori diversi del rank
ci sono al più n/F(i) nodi nel blocco B(i)
Prova di 2.
(n/2r) per (F(i-1) +1 ≤ r ≤ F(i))
= (n/2r) per 0 ≤ r ≤ F(i)) - (n/2r) per 0 ≤ r ≤ F(i-1) +1 )=
= n(1/2) F(i) +1 -1 / (1/2-1) - n(1/2) F(i-1) +2-1 / (1/2-1)≤
≤ n (1/2) F(i-1) +1 - (1/2) F(i) +1  / 1/2 
≤ n (1/2) F(i-1) +1  / 1/2 
≤ n /2F(i-1)
= n /F(i)
Il risultato migliore
Una qualunque sequenza di n operazioni makeset, m operazioni find e al più
(n-1) operazioni union può essere realizzata in tempo O(n+m(m+n,n)
funzione di Ackermann
A(1,j) = 2j j≥1
A(i,1) = A(i-1,2) per i≥2
A(i,j) = A(i-1, A(i,j-1) per i,j≥2
 funzione inversa della funzione di Ackermann
Scarica