1 / 42

Per valutare la complessità ammortizzata scomponiamo ogni Union :

Per valutare la complessità ammortizzata scomponiamo ogni Union :. Union ( x , y ) x = FindSet ( x ) y = FindSet ( y ) Link ( x , y ).

emmett
Télécharger la présentation

Per valutare la complessità ammortizzata scomponiamo ogni Union :

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Per valutare la complessità ammortizzata scomponiamo ogni Union: Union(x, y) x= FindSet(x) y= FindSet(y) Link(x, y) nelle due FindSet e nella Link che la costituiscono e valuteremo la complessità in funzione del numero m di operazioni MakeSet, FindSet e Link così ottenute.

  2. Se m' è il numero di operazioni MakeSet, FindSet e Union della sequenza originale allora m' m 3m' Quindi possiamo calcolare la complessità asintotica in funzione di m invece che di m'. Useremo il metodo del potenziale. Per definire la funzione potenziale ci servono alcune premesse.

  3. FindSet(x) ifx.p x x.p =FindSet(x.p) returnx.p MakeSet(x) x.p = x x.rank = 0 Link(x, y) ifx.rank> y.rank y.p =x else x.p =y ifx.rank == y.rank y.rank = y.rank+ 1

  4. Proprietà dei ranghi Per ogni nodo x • x viene creato come radice con x.rank= 0 • x.rankaumenta soltanto finché x resta radice, dopo di che rimane invariato. • Se x non è radice x.rank< x.p.rank • x.p.rankpuò solo aumentare. • dopo aver eseguito n operazioni x.rank< n

  5. Valgono le seguenti diseguaglianze Le due funzioni level(x) e iter(x) Per ogninodo x non radice definiamo due funzioni che “misurano” la differenza di rango tra x e x.p.

  6. Dimostrazione:

  7. (x) soddisfa le diseguaglianze Nel primo caso Ad ogni nodo xattribuiamo un potenziale (o credito)

  8. Nel secondo caso

  9. Valutiamo la differenza di potenziale dovuta alla i-esima operazione: Definiamo unpotenziale globale come somma dei potenziali di tutti i nodi

  10. Se la i-esima operazione è una MakeSet(x) il potenziale del nodo x è 0 mentre il potenziale degli altri nodi rimane invariato. Quindi

  11. Supponiamo quindi che la i-esima operazione sia una Link o FindSet. Dimostriamo che se x non è radice il potenziale di x non può aumentare, ossia Ed inoltre che se x.rank 1 e la i-esima operazione modifica o level(x) o iter(x) il potenziale diminuisce

  12. Se x.rank= 0 Supponiamo x.rank 1. Se level(x) e iter(x) non cambiano Se level(x) non cambia ma cambia iter(x) allora iter(x) può solo crescere e quindi Dimostrazione: Se x non è radice x.ranknon cambia. Inoltre Link e FindSet non cambiano n e quindi anche (n) non cambia.

  13. Se level(x) cambia, iter(x) può anche diminuire ma, per i limiti visti, un aumento di level(x) diminuisce (x) di almeno x.rankmentre una diminuzione diiter(x) aumenta (x) al più di x.rank-1. Anche in questo caso

  14. Calcoliamo il costo ammortizzato delle tre operazioni MakeSet(x) x.p = x x.rank = 0 Link(x, y) ifx.rank> y.rank y.p =x else x.p =y ifx.rank == y.rank y.rank = y.rank+ 1 FindSet(x) ifx.p x x.p =FindSet(x.p) returnx.p

  15. Costo ammortizzato di MakeSet(x)

  16. Costo ammortizzato di Link(x,y) Il potenziale (x) dipende soltanto da x.ranke x.p.rank. Quindi gli unici elementi il cui potenziale può cambiare sono x, y e i figli di y. I figli di y non sono radici e il loro potenziale non può aumentare.

  17. Se x.rank= 0 Altrimenti x è radice e diventa figlio di y ma il suo rango non cambia.

  18. Dunque ed il costo ammortizzato di Link è y rimane radice e y.ranko rimane invariato o aumenta di 1. Quindi

  19. Costo ammortizzato di FindSet(x) Il costo reale è proporzionale al numero s di nodi del cammino percorso. Il potenziale della radice non cambia mentre i potenziali degli altri nodi possono solo diminuire. Consideriamo dapprima come cambia il potenziale dei nodi x del cammino che hanno x.rank> 0 e che sono seguiti da almeno un nodo y diverso dalla radice e tale che level(y) = level(x).

  20. Sia k= level(y) = level(x). Allora dopo la compressione Dunque iter(x) aumenta di almeno 1 e quindi

  21. ed il costo ammortizzato di FindSet è I nodi rimanenti sono la radice, il primo nodo se ha rango 0 e per ogni livello k l’ultimo nodo del cammino avente level(x) = k. Siccome i livelli distinti sono al più (n) ci sono al più (n)+2 nodi il cui potenziale può rimanere invariato mentre il potenziale degli altri s-(n)-2 diminuisce di almeno 1. Quindi

  22. w v u Esercizio 31 . (Problema 22-3 del libro.) In un albero T il minimo antenato comune di due nodi u e v è il nodo w a profondità massima che è antenato sia di u che di v.

  23. Nel problema dei minimi comuni antenati off-linesono dati un albero T con n nodi ed una lista L = (u1,v1), ... ,(um,vm) di m coppie di nodi Si chiede di calcolare la lista W = w1, ... ,wm dei minimi comuni antenati di ogni coppia.

  24. L’algoritmo di Tarjan risolve il problema in tempo lineare O(n+m) con una sola percorrenza dell’albero. • I nodi dell’albero hanno i seguenti campi: • - child:punta al primo figlio • - sibling: punta al fratello • - ancestor: punta ad un antenato • color : whiteall’inizio e poi diventa black. • oltre ai campi p e rank per insiemi disgiunti.

  25. L’algoritmo di Tarjan: MinComAnt(u) MakeSet(u) u.ancestor= u v = u.child whilev ≠ nil//percorre la lista dei figli MinComAnt(v) Union(u,v) FindSet(u).ancestor= u v = v.sibling u.color= black for“ognivtale che (u,v) ≡ (ui,vi)  L” ifv.color == black wi = FindSet(v).ancestor

  26. x0 = root, xk = u MinComAnt(u) S0 x0 ri= rappresentante S1 x1 S2 x2 r0 ...... r1 r2 Sk-1 xk-1 xk rk-1

  27. Esercizio 30 . (Problema 22-1 del libro) Sia dato l’insieme T = {1, 2, ... , n} ed una sequenza S = {o1, o2, ... , on+m}di n+m operazioni delle quali n sono Insertche inseriscono gli elementi di Tuna e una sola volta ed msono ExtractMin che estraggono il minimo tra gli elementi inseriti e non ancora estratti. Supponiamo che ogni ExtractMin della sequenza sia preceduta da più Insert che ExtractMin.

  28. Una possibile sequenza con n = 9 ed m = 6 è: S = { 4, 8, E1, 3, E2, 9, 2, 6, E3, E4, E5, 1, 7, E6, 5 } In cui le Insertsono indicate con i valori 1, 2,..., n inseriti mentre le ExtractMinsono indicate con Ej per j = 1,…, m.

  29. Si chiede un algoritmo efficiente che data la sequenza S di operazioni calcoli la sequenza X = {x1, x2, ..., xm} degli m elementi estratti. Ad esempio, con S = { 4, 8, E1, 3, E2, 9, 2, 6, E3, E4, E5, 1, 7, E6, 5 } Il risultato dovrebbe essere X = {4, 3, 2, 6, 8, 1}

  30. Soluzione. Per ogni valore i = 1,…,ncalcoliamo l’indice j dell’operazione ExtractMin che lo estrae e poniamo Xj=i. Se i non viene estratto poniamo j =m+1 e non memorizziamo i in X.

  31. Consideriamo la sequenza dell’esempio in cui abbiamo aggiunto alla fine un contenitore C7 a cui associare i valori non estratti. S ={4, 8, E1, 3, E2, 9, 2, 6, E3, E4, E5, 1, 7, E6, 5, C7} L’elemento 1 viene estratto da E6. Poniamo quindi X6=1 e a questo punto l’estrazione E6 è stata effettuata.

  32. La situazione è: S ={4, 8, E1, 3, E2, 9, 2, 6, E3, E4, E5, 1, 7, E6, 5, C7} X={#, #, #, #, #, 1} L’elemento 2 viene estratto da E3. Quindi X3=2 S ={4, 8, E1, 3, E2, 9, 2, 6, E3, E4, E5, 1, 7, E6, 5, C7} X={#, #, 2, #, #, 1} L’elemento 3 viene estratto da E2. Quindi X2=3 S ={4, 8, E1, 3, E2, 9, 2, 6, E3, E4, E5, 1, 7, E6, 5, C7} X={#, 3, 2, #, #, 1} L’elemento 4 viene estratto da E1. Quindi X1=4

  33. La situazione è S ={4, 8, E1, 3, E2, 9, 2, 6, E3, E4, E5, 1, 7, E6, 5, C7} X={4, 3, 2, #, #, 1} L’elemento 5 non viene estratto e rimane associato a C7. Noi infatti manteniamo associato ogni valore alla ExtractMin successiva non ancora effettuata o a C7 se non ce ne sono altre. L’elemento 6 è associato ad E4 e quindi X4=6.

  34. La situazione è S ={4, 8, E1, 3, E2, 9, 2, 6, E3, E4, E5, 1, 7, E6, 5, C7} X={4, 3, 2, 6, #, 1} L’elemento 7 è associato a C7 e viene scartato. L’elemento 8 è associato ad E5 e quindi X5=8. S ={4, 8, E1, 3, E2, 9, 2, 6, E3, E4, E5, 1, 7, E6, 5, C7} X={4, 3, 2, 6, 8, 1} L’elemento 9 è associato a C7 e viene scartato. Il risultato è quindi X = {4, 3, 2, 6, 8, 1}

  35. Implementazione. Usiamo una struttura dati per insiemi disgiunti. Manteniamo raggruppati in un insieme Ij gli elementi associati ad ogni Ej non ancora effettuata e in un insieme Im+1 quelli associati a Cm+1.

  36. Su questi insiemi vogliamo eseguire in tempo costante le operazioni MakeSet(i), Union(i,h), FindSet(i) ed inoltre FindIndex(i) che calcola l’indice j della Ej non effettuata (o l’indice m+1 di Cm+1) a cui l’elemento i risulta associato. Le prime tre sono quelle standard e per poter eseguire la FindIndex(i) basta memorizzare nel rappresentante di ogni insieme l’indice j della Ej non effettuata (o l’indice m+1 di Cm+1) a cui l’insieme è associato.

  37. Rimane un problema: qualcuno degli insiemi può essere vuoto mentre la struttura dati per insiemi disgiunti richiede che essi siano tutti non vuoti. Per ovviare a questo aggiungiamo ad ogni insieme Ij un elemento fittizio di valore i = n+j. All’inizio creiamo quindi m+1 insiemi I1,…,Im+1 dove Ij = {n+j} contiene soltanto l’elemento fittizio e memorizziamo l’indice j nell’unico nodo. Tempo O(m).

  38. Percorriamo quindi la sequenza delle operazioni e, finché non troviamo la prima ExtractMin, aggiungiamo gli elementi inseriti all’insieme I1. Dopo di che gli elementi inseriti prima della seconda ExtractMin vengono aggiunti a I2 e così via fino ad aggiungere ad Im+1 tutti gli elementi inseriti dopo l’ultima ExtractMin. Tempo O(n+m).

  39. Per aggiungere un nuovo elemento i ad un insieme Ij dobbiamo usare la MakeSet(i) e poi usare la Union(i, m+j) per riunire i due insiemi (ricordiamo che m+j è l’elemento fittizio di Ij ). Naturalmente se l’unione cambia il rappresentante occorre ricordarsi di memorizzare l’indice j dell’insieme nel nuovo rappresentante.

  40. Quando il nostro algoritmo decide che l’elemento i viene estratto da Ej dobbiamo porre X[j]=i A questo punto, siccome Ejè stata eseguita, gli elementi dell’insieme Ij a cui appartiene i devono essere associati alla successiva ExtractMinEk non ancora eseguita o a Cm+1 se tutte le ExtractMinsuccessive sono state eseguite.

  41. Occorre quindi effettuare una Union(i,h)dove h è un elemento di Ik associato ad Ek o di Im+1 associato a Cm+1. Dobbiamo però prima trovare h. Per fare questo manteniamo i rappresentanti degli insiemi Ij in una lista doppiamente concatenata e ordinata rispetto all’indice j.

  42. Supponiamo di aver elaborato gli elementi 1,…,i-1. Per trovare l’indice j della ExtractMin non saturata che estrae i basta calcolare j =FindIndex(i). Se j = m+1 l’elemento i è stato inserito dopo l’ultima ExtractMin non saturata e quindi non viene estratto. Altrimenti esso è estratto da Ej e possiamo porre X[j]=i. Tutto questo richiede un tempo costante per ciascun elemento e quindi tempo O(n) in totale.

More Related