Per valutare la complessità ammortizzata scomponiamo ogni Union: nelle due FindSet e nella Link che la costituiscono e valuteremo la complessità in funzione.

Slides:



Advertisements
Presentazioni simili
Premessa: si assume di aver risolto (correttamente
Advertisements

Algoritmi e Strutture dati Mod B
Strutture dati per insiemi disgiunti
Algoritmi e Strutture Dati
Algoritmi e Strutture Dati
Lez. 121 Universita' di Ferrara Facolta' di Scienze Matematiche, Fisiche e Naturali Laurea Specialistica in Informatica Algoritmi Avanzati Progettazione.
RB-alberi (Red-Black trees)
Hash Tables Indirizzamento diretto Tabelle Hash Risoluzioni di collisioni Indirizzamento aperto.
Breath-first search Visita in ampiezza di un grafo Algoritmo Esempio
Alberi binari di ricerca
Breath-first search Visita in ampiezza di un grafo Algoritmo Esempio
Insiemi disgiunti.
Algoritmi e Dimostrazioni Stefano Berardi
Capitolo 3 Strutture dati elementari Algoritmi e Strutture Dati.
Algoritmi e Strutture Dati
Capitolo 3 Strutture dati elementari Algoritmi e Strutture Dati.
Algoritmi e Strutture Dati
U V U V (a) |cfc|=2 prima e dopo (b) |cfc|=2 prima e |cfc|=1 dopo
1 Strutture dati avanzate Vedremo alcune strutture dati che permettono di eseguire in modo particolarmente efficiente un determinato insieme di operazioni.
Algoritmi e strutture Dati - Lezione 7
Il problema del dizionario
Algoritmi e Strutture Dati
Capitolo 9 Il problema della gestione di insiemi disgiunti (Union-find) Algoritmi e Strutture Dati.
Algoritmi e Strutture Dati
Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale.
Algoritmi e Strutture Dati Alberi Binari di Ricerca.
Algoritmi e Strutture Dati (Mod. B)
Algoritmi e Strutture Dati (Mod. A)
Algoritmi e Strutture Dati
Modello dati ALBERO Albero: Albero: insieme di punti chiamati NODI e linee chiamate EDGES EDGE: linea che unisce due nodi distinti Radice (root): in una.
Modello dati ALBERO Albero: Albero: insieme di punti chiamati NODI e linee chiamate EDGES EDGE: linea che unisce due nodi distinti Radice (root): in una.
Sottoinsiemi disgiunti
Heap binari e HeapSort.
Heap binomiali Gli heap binomiali sono strutture dati su cui si possono eseguire efficientemente le operazioni: Make(H) : crea uno heap vuoto Insert(H,
Fibonacci Heaps e il loro utilizzo nell’algoritmo di Prim
Tavole dinamiche Spesso non si sa a priori quanta memoria serve per memorizzare dei dati in un array, in una tavola hash, in un heap, ecc. Può capitare.
Anche la RB-Delete ha due fasi: Nella prima viene tolto un nodo y avente uno dei sottoalberi vuoto sostituendolo con la radice dellaltro sottoalbero. Per.
Metodo della moltiplicazione
Esercizio 10.* Un cassiere vuole dare un resto di n centesimi di euro usando il minimo numero di monete. a) Descrivere un algoritmo goloso per fare ciò.
Strutture dati per insiemi disgiunti
Radix-Sort(A,d) // A[i] = cd...c2c1
Passo 3: calcolo del costo minimo
Vedremo in seguito che (n log n) è un limite stretto per il problema dellordinamento. Per ora ci limitiamo a dimostrare che: La complessità nel caso pessimo.
Cerchiamo di rispondere alla seconda domanda 2)La soluzione trovata con lalgoritmo goloso è ottima o esistono anche soluzioni con più di quattro attività?
Ispezione lineare La funzione hash h(k,i) si ottiene da una funzione hash ordinaria h'(k) ponendo L’esplorazione inizia dalla cella h(k,0) = h'(k) e continua.
RB-insert(T, z) // z.left = z.right = T.nil Insert(T, z) z.color = RED // z è rosso. Lunica violazione // possibile delle proprietà degli alberi // rosso-neri.
Algoritmi e Strutture Dati
La complessità media O(n log n) di Quick-Sort vale soltanto se tutte le permutazioni dell’array in ingresso sono ugualmente probabili. In molte applicazioni.
Capitolo 3 Strutture dati elementari Algoritmi e Strutture Dati Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano.
Valutare la difficoltà dei problemi
Implementazione di dizionari Problema del dizionario dinamico Scegliere una struttura dati in cui memorizzare dei record con un campo key e alcuni altri.
Capitolo 9 Il problema della gestione di insiemi disgiunti (Union-find) Algoritmi e Strutture Dati.
Risoluzione delle collisioni con indirizzamento aperto Con la tecnica di indirizzamento aperto tutti gli elementi stanno nella tavola. La funzione hash.
Alberi rosso-neri Le operazioni sugli alberi binari di ricerca hanno complessità proporzionale all’altezza h dell’albero. Gli alberi rosso-neri sono alberi.
1 Ordinamento (Sorting) INPUT: Sequenza di n numeri OUTPUT: Permutazione π = tale che a 1 ’  a 2 ’  … …  a n ’ Continuiamo a discutere il problema dell’ordinamento:
Algoritmi e strutture Dati - Lezione 7 1 Algoritmi di ordinamento ottimali L’algoritmo Merge-Sort ha complessità O(n log(n))  Algoritmo di ordinamento.
1 Analisi ammortizzata Si considera il tempo richiesto per eseguire, nel caso pessimo, una intera sequenza di operazioni. Se le operazioni costose sono.
Capitolo 9 Union-find Algoritmi e Strutture Dati.
Capitolo 12 Minimo albero ricoprente: Algoritmo di Kruskal Algoritmi e Strutture Dati.
Master Bioinformatica 2002: Visite di Grafi La struttura dati D è una PILA (STACK) Visita in profondità o Depth-First-Search (DFS)
1 Ordinamento (Sorting) Input: Sequenza di n numeri Output: Permutazione π = tale che: a i 1  a i 2  ……  a i n Continuiamo a discutere il problema dell’ordinamento:
Codici prefissi Un codice prefisso è un codice in cui nessuna parola codice è prefisso (parte iniziale) di un’altra Ogni codice a lunghezza fissa è ovviamente.
Master Bioinformatica 2002: Visite di Grafi Algoritmi di visita Scopo: visitare tutti i vertici di un grafo per scoprirne proprietà di vario tipo. Alcune.
Flusso di Costo Minimo Applicazione di algoritmi: Cammini Minimi Successivi (SSP) Esercizio 1 Sia data la seguente rete di flusso, in cui i valori riportati.
Problemi risolvibili con la programmazione dinamica Abbiamo usato la programmazione dinamica per risolvere due problemi. Cerchiamo ora di capire quali.
Complessità Computazionale
Come aumentare gli alberi
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Capitolo 12 Minimo albero ricoprente: Algoritmo di Prim Algoritmi e Strutture.
Capitolo 9 Il problema della gestione di insiemi disgiunti (Union-find) Algoritmi e Strutture Dati.
Capitolo 12 Minimo albero ricoprente: Algoritmo di Kruskal Algoritmi e Strutture Dati.
Transcript della presentazione:

Per valutare la complessità ammortizzata scomponiamo ogni Union: 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. Union(x, y) x = FindSet(x) y = FindSet(y) Link(x, y)

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.

MakeSet(x) x.p = x x.rank = 0 FindSet(x) if x.p x x.p = FindSet(x.p) return x.p Link(x, y) if x.rank > y.rank y.p = x else x.p = y if x.rank == y.rank y.rank = y.rank + 1

Proprietà dei ranghi Per ogni nodo x a) x viene creato come radice con x.rank = 0 b) x.rank aumenta soltanto finché x resta radice, dopo di che rimane invariato. c) Se x non è radice x.rank < x.p.rank d) x.p.rank può solo aumentare. e) dopo aver eseguito n operazioni x.rank < n

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

Dimostrazione:

Ad ogni nodo x attribuiamo un potenziale (o credito) (x) soddisfa le diseguaglianze Nel primo caso

Nel secondo caso

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

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

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 Supponiamo quindi che la i-esima operazione sia una Link o FindSet.

Dimostrazione: Se x non è radice x.rank non cambia. Inoltre Link e FindSet non cambiano n e quindi anche (n) non cambia. 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

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

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

Costo ammortizzato di MakeSet(x)

Costo ammortizzato di Link(x,y) Il potenziale (x) dipende soltanto da x.rank e 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.

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

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

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).

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

I nodi rimanenti sono la radice, il primo nodo se ha rango 0 e per ogni livello k lultimo 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 ed il costo ammortizzato di FindSet è

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. u v w

Nel problema dei minimi comuni antenati off-line sono dati un albero T con n nodi ed una lista L = (u 1,v 1 ),...,(u m,v m ) di m coppie di nodi Si chiede di calcolare la lista W = w 1,...,w m dei minimi comuni antenati di ogni coppia.

Lalgoritmo di Tarjan risolve il problema in tempo lineare O(n+m) con una sola percorrenza dellalbero. I nodi dellalbero hanno i seguenti campi: - child : punta al primo figlio - sibling : punta al fratello - ancestor : punta ad un antenato - color : white allinizio e poi diventa black. oltre ai campi p e rank per insiemi disgiunti.

MinComAnt(u) MakeSet(u) u.ancestor = u v = u.child while v nil // percorre la lista dei figli MinComAnt(v) Union(u,v) FindSet(u).ancestor = u v = v.sibling u.color = black for ogni v tale che (u,v) (u i,v i ) L if v.color == black w i = FindSet(v).ancestor Lalgoritmo di Tarjan:

x0x0 x1x1 x2x r0r0 r1r1 r k-1 S0S0 S1S1 S2S2 S k-1 x k-1 r2r2 r i = rappresentante MinComAnt(u) x 0 = root, x k = u xkxk

Esercizio 30. (Problema 22-1 del libro) Sia dato linsieme T = {1, 2,..., n} ed una sequenza S = {o 1, o 2,..., o n+m } di n+m operazioni delle quali n sono Insert che inseriscono gli elementi di T una e una sola volta ed m sono 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.

Una possibile sequenza con n = 9 ed m = 6 è: In cui le Insert sono indicate con i valori 1, 2,..., n inseriti mentre le ExtractMin sono indicate con E j per j = 1,…, m. S = { 4, 8, E 1, 3, E 2, 9, 2, 6, E 3, E 4, E 5, 1, 7, E 6, 5 }

Si chiede un algoritmo efficiente che data la sequenza S di operazioni calcoli la sequenza X = {x 1, x 2,..., x m } degli m elementi estratti. Il risultato dovrebbe essere Ad esempio, con X = {4, 3, 2, 6, 8, 1} S = { 4, 8, E 1, 3, E 2, 9, 2, 6, E 3, E 4, E 5, 1, 7, E 6, 5 }

Soluzione. Per ogni valore i = 1,…,n calcoliamo lindice j delloperazione ExtractMin che lo estrae e poniamo X j = i. Se i non viene estratto poniamo j = m+1 e non memorizziamo i in X.

S ={4, 8, E 1, 3, E 2, 9, 2, 6, E 3, E 4, E 5, 1, 7, E 6, 5, C 7 } Consideriamo la sequenza dellesempio in cui abbiamo aggiunto alla fine un contenitore C 7 a cui associare i valori non estratti. Lelemento 1 viene estratto da E 6. Poniamo quindi X 6 = 1 e a questo punto lestrazione E 6 è stata effettuata.

Lelemento 2 viene estratto da E 3. Quindi X 3 = 2 S ={4, 8, E 1, 3, E 2, 9, 2, 6, E 3, E 4, E 5, 1, 7, E 6, 5, C 7 } X ={#, #, 2, #, #, 1} S ={4, 8, E 1, 3, E 2, 9, 2, 6, E 3, E 4, E 5, 1, 7, E 6, 5, C 7 } X ={#, #, #, #, #, 1} La situazione è: Lelemento 3 viene estratto da E 2. Quindi X 2 = 3 S ={4, 8, E 1, 3, E 2, 9, 2, 6, E 3, E 4, E 5, 1, 7, E 6, 5, C 7 } X ={#, 3, 2, #, #, 1} Lelemento 4 viene estratto da E 1. Quindi X 1 = 4

Lelemento 5 non viene estratto e rimane associato a C 7. Noi infatti manteniamo associato ogni valore alla ExtractMin successiva non ancora effettuata o a C 7 se non ce ne sono altre. Lelemento 6 è associato ad E 4 e quindi X 4 = 6. S ={4, 8, E 1, 3, E 2, 9, 2, 6, E 3, E 4, E 5, 1, 7, E 6, 5, C 7 } X ={4, 3, 2, #, #, 1} La situazione è

Lelemento 7 è associato a C 7 e viene scartato. Lelemento 9 è associato a C 7 e viene scartato. Il risultato è quindi X = {4, 3, 2, 6, 8, 1} S ={4, 8, E 1, 3, E 2, 9, 2, 6, E 3, E 4, E 5, 1, 7, E 6, 5, C 7 } X ={4, 3, 2, 6, #, 1} Lelemento 8 è associato ad E 5 e quindi X 5 = 8. S ={4, 8, E 1, 3, E 2, 9, 2, 6, E 3, E 4, E 5, 1, 7, E 6, 5, C 7 } X ={4, 3, 2, 6, 8, 1} La situazione è

Implementazione. Usiamo una struttura dati per insiemi disgiunti. Manteniamo raggruppati in un insieme I j gli elementi associati ad ogni E j non ancora effettuata e in un insieme I m+1 quelli associati a C m+1.

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

Rimane un problema: qualcuno degli insiemi può essere vuoto mentre la struttura dati per insiemi disgiunti richiede che essi siano tutti non vuoti. Allinizio creiamo quindi m+1 insiemi I 1,…,I m+1 dove I j = {n+j} contiene soltanto lelemento fittizio e memorizziamo lindice j nellunico nodo. Tempo O(m). Per ovviare a questo aggiungiamo ad ogni insieme I j un elemento fittizio di valore i = n+j.

Percorriamo quindi la sequenza delle operazioni e, finché non troviamo la prima ExtractMin, aggiungiamo gli elementi inseriti allinsieme I 1. Dopo di che gli elementi inseriti prima della seconda ExtractMin vengono aggiunti a I 2 e così via fino ad aggiungere ad I m+1 tutti gli elementi inseriti dopo lultima ExtractMin. Tempo O(n+m).

Per aggiungere un nuovo elemento i ad un insieme I j dobbiamo usare la MakeSet(i) e poi usare la Union(i, m+j) per riunire i due insiemi (ricordiamo che m+j è lelemento fittizio di I j ). Naturalmente se lunione cambia il rappresentante occorre ricordarsi di memorizzare lindice j dellinsieme nel nuovo rappresentante.

Quando il nostro algoritmo decide che lelemento i viene estratto da E j dobbiamo porre X[j] = i A questo punto, siccome E j è stata eseguita, gli elementi dellinsieme I j a cui appartiene i devono essere associati alla successiva ExtractMin E k non ancora eseguita o a C m+1 se tutte le ExtractMin successive sono state eseguite.

Dobbiamo però prima trovare h. Per fare questo manteniamo i rappresentanti degli insiemi I j in una lista doppiamente concatenata e ordinata rispetto allindice j. Occorre quindi effettuare una Union(i,h) dove h è un elemento di I k associato ad E k o di I m+1 associato a C m+1.

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