La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

Algoritmi e Strutture Dati

Presentazioni simili


Presentazione sul tema: "Algoritmi e Strutture Dati"— Transcript della presentazione:

1 Algoritmi e Strutture Dati
Capitolo 10 - Code con priorità e insiemi disgiunti Alberto Montresor Università di Trento This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike License. To view a copy of this license, visit or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA. © Alberto Montresor

2 Strutture dati viste finora Sequenze, insiemi e dizionari
Introduzione Strutture dati viste finora Sequenze, insiemi e dizionari Strutture “speciali” Le operazioni base (inserimento, cancellazione, lettura, etc.) possono non essere sufficienti: a volte è necessario inventarsene di nuove Se non tutte le operazioni sono necessarie, è possibile realizzare strutture dati più efficienti, “specializzate” per particolare compiti © Alberto Montresor

3 Gli oggetti vengono estratti dalla coda in base alla loro priorità
Code con priorità L'idea Una struttura dati – detta heap – che mantiene dati in modo parzialmente ordinato Utilizzazioni Code con priorità Gli oggetti vengono estratti dalla coda in base alla loro priorità Heapsort Algoritmo di ordinamento Costo computazionale: O(n log n) Ordinamento sul posto © Alberto Montresor

4 Albero binario perfetto Tutte le foglie hanno la stessa profondità h
Alberi binari Albero binario perfetto Tutte le foglie hanno la stessa profondità h Nodi interni hanno grado 2 Un albero perfetto Ha altezza ⎣log N⎦ Altezza h → #nodi= 2h+1-1 Albero binario completo Tutte le foglie hanno profondità h o h-1 Tutti i nodi a livello h sono “accatastati” a sinistra Tutti i nodi interni hanno grado 2, eccetto al più uno © Alberto Montresor

5 Un albero binario completo è un albero max-heap sse
Alberi binari heap Max heap Un albero binario completo è un albero max-heap sse Ad ogni nodo i viene associato un valore A[i] A[p(i)] ≥ A[i] Un albero binario completo è un albero min-heap sse A[p(i)] ≤ A[i] Le definizioni e gli algoritmi di max-heap sono simmetrici rispetto a min-heap 16 14 10 8 7 9 3 2 4 1 © Alberto Montresor

6 Alcune informazioni sugli alberi heap
Un albero heap non impone alcuna relazione di ordinamento fra i figli di un nodo Un albero heap è un ordinamento parziale Riflessivo: Ogni nodo è ≥ di se stesso Antisimmetrico: se n≥m e m≥n, allora m=n Transitivo: se n≥m e m≥r, allora n≥r Ordinamenti parziali Utili per modellare gerarchie complesse o mantenere informazioni parziali Nozione più debole di un ordinamento totale... Ma più semplice da costruire 16 16 14 14 10 10 {a,b} {a} {b} © Alberto Montresor

7 Array heap E' possibile rappresentare un albero binario heap tramite un array heap (oltre che tramite puntatori) Come è fatto? Array A[1..n] Come è organizzato? A[1] contiene la radice p(i) = ⎣i/2⎦ l(i) = 2i r(i) = 2i+1 A[1] 16 A[2] A[3] 14 10 A[4] A[5] A[6] A[7] 8 7 9 3 A[8] 2 4 1 A[10] A[9] n = 10 16 14 10 8 7 9 3 2 4 1 © Alberto Montresor

8 www.xkcd.com Array heap Ricapitolando:
Array max-heap: A[i] ≥ A[2i], A[i] ≥ A[2i+1] Procedure per gestire heap maxHeapRestore - O(log n) Un algoritmo che mantiene la proprietà di max-heap heapBuild - O(n) Un algoritmo che costruisce un max-heap da zero heapsort - O(n log n) Ordina sul posto un array © Alberto Montresor

9 Gli alberi binari con radici l(i) e r(i) sono max-heap
maxHeapRestore() Input Un array A e un indice i Gli alberi binari con radici l(i) e r(i) sono max-heap E' possibile che A[i] sia minore di A[l(i)] o A[r(i)] In altre parole: il sottoalbero con radice i può non essere un max-heap Scopo Ripristinare la proprietà di max-heap sul sottoalbero con radice i Facendo “scendere” l'elemento A[i] nell'array © Alberto Montresor

10 maxHeapRestore() © Alberto Montresor

11 Domanda: Esempio di funzionamento 5, 15, 12, 9, 10, 7, 4, 3, 6, 8, 2
maxHeapRestore() Domanda: Esempio di funzionamento 5, 15, 12, 9, 10, 7, 4, 3, 6, 8, 2 E' un array max-heap? E' possibile applicare maxHeapRestore() alla radice? Domanda: Qual è la complessità in tempo di maxHeapRestore()? Domanda Dimostrare la correttezza di maxHeapRestore() © Alberto Montresor

12 Sia A[1..n] un array da ordinare
heapBuild() Principio generale Sia A[1..n] un array da ordinare Tutti i nodi A[⎣n/2⎦ n] sono foglie dell'albero e quindi heap di un elemento da cui iniziare La procedura heapBuild() attraversa i restanti nodi dell'albero ed esegue maxHeapRestore() © Alberto Montresor

13 Domanda: Esempio di funzionamento
heapBuild() Domanda: Esempio di funzionamento 14, 45, 28, 34, 15, 20, 12, 30, 21, 25, 16, 22 Domanda: Correttezza Esprimere un'invariante di ciclo Dimostrare la sua correttezza Domanda – Complessità Qual è la complessità di heapBuild()? 14 45 28 34 15 20 12 30 21 25 16 22 © Alberto Montresor

14 Viene eseguito ⎡n/2⎤ volte su heap di altezza 0
Complessità Le operazioni maxHeapRestore() vengono eseguite su heap di altezza variabile Viene eseguito ⎡n/2⎤ volte su heap di altezza 0 Viene eseguito ⎡n/4⎤ volte su heap di altezza 1 Viene eseguito ⎡n/8⎤ volte su heap di altezza 2 ...Viene eseguito ⎡n/2h+1⎤ volte su heap di altezza h Da cui si deduce Ricordate: Per x < 1 © Alberto Montresor

15 Ordinamento tramite heap
Intuizione Il primo elemento dello heap è sempre il massimo Andrebbe collocato nell'ultima posizione L'elemento in ultima posizione? In testa! Chiama maxHeapRestore() per ripristinare la situazione © Alberto Montresor

16 Domanda: Esempio di funzionamento
heapsort() Domanda: Esempio di funzionamento 14, 45, 28, 34, 15, 20, 12, 30, 21, 25, 16, 22 Domanda: Correttezza Esprimere un'invariante di ciclo Dimostrare la sua correttezza Domanda: Complessità Qual è la complessità di heapsort()? 45 34 28 30 25 22 12 14 21 15 16 20 © Alberto Montresor

17 Dimostrare che uno heap con n nodi ha altezza θ(log n)
Esercizi Esercizio Dimostrare che uno heap con n nodi ha altezza θ(log n) Scrivere un'implementazione iterativa di maxHeapRestore() (in pseudo-codice) Dimostrare che il tempo di esecuzione nel caso peggiore di maxHeapRestore() è Ω(log n) Implementare heapsort() nel vostro linguaggio preferito © Alberto Montresor

18 Code con priorità Coda con priorità
Una struttura dati che serve a mantenere un insieme S di elementi x, ciascuno con un valore associato di priorità © Alberto Montresor

19 Specifica © Alberto Montresor

20 Simulatore event-driven
Code con priorità Esempio di utilizzo Simulatore event-driven Ad ogni evento è associato un timestamp di esecuzione Ogni evento può generare nuovi eventi, con timestamp arbitrari Una coda con min-priorità può essere utilizzata per eseguire gli eventi in ordine di timestamp Esempi di organizzazione p 3 ev p 3 ev evento p 4 ev p 5 ev p 6 ev p p 7 ev p 8 ev 5 ev p 7 ev © Alberto Montresor

21 Code con priorità © Alberto Montresor

22 Inserimento © Alberto Montresor

23 Code con priorità - minHeapRestore()
© Alberto Montresor

24 Rimozione del minimo e riduzione priorità
© Alberto Montresor

25 Qual è la complessità delle operazioni sulle code con priorità?
Esercizio Qual è la complessità delle operazioni sulle code con priorità? Scrivere lo pseudocodice di una versione heapBuild() basata sulla insert() Le due procedure creano lo stesso heap? Dimostrare o produrre un esempio contrario Qual è la complessità di questa versione di heapBuild()? L'azione di delete(PriorityItem x) cancella l'elemento x dallo heap. Scrivete una versione di delete() che operi in tempo O(log n). © Alberto Montresor

26 Struttura dati per insiemi disgiunti
Motivazioni In alcune applicazioni siamo interessati a gestire insiemi disgiunti di oggetti Esempio: componenti di un grafo Operazioni fondamentali: unire più insiemi identificare l'insieme a cui appartiene un oggetto Struttura dati Una collezione S = { S1, S2, ..., Sn } di insiemi dinamici disgiunti Ogni insieme è identificato da un rappresentante univoco © Alberto Montresor

27 Scelta del rappresentante
Il rappresentante può essere un qualsiasi membro dell’insieme Si Operazioni di ricerca del rappresentante su uno stesso insieme devono restituire sempre lo stesso oggetto Solo in caso di unione con altro insieme il rappresentante può cambiare Il rappresentante può essere un elemento specifico dell’insieme Si devono definire le caratteristiche degli insiemi e una regola per caratterizzare il rappresentante Esempio: l’elemento più piccolo/grande di un insieme © Alberto Montresor

28 Primitive degli insiemi disgiunti (Merge-Find)
© Alberto Montresor

29 Esempio mfset(6) 1 2 3 4 5 6 merge(1,2) 1 2 3 4 5 6 1, 2 merge(3,4) 1
5,6 merge(1,3) 1 2 3 4 5 6 1, 2, 3, 4 5,6 merge(1,5) 1, 2, 3, 4, 5, 6 1 2 3 4 5 6 © Alberto Montresor

30 Esempio: come utilizzare Merge-Find
Determinare le componenti connesse di un grafo non orientato dinamico Algoritmo Si inizia con componenti connesse costituite da un unico vertice L'operazione merge(find(u), find(v)) viene eseguita per ogni arco (u,v) Alla fine, avremo l'insieme delle componenti connesse Complessità Costo: O(n) + m operazioni merge() Questo algoritmo è interessante per la capacità di gestire grafi dinamici (in cui gli archi vengono aggiunti) © Alberto Montresor

31 Implementazione di Union-Find
Algoritmi elementari: Realizzazione basata su liste find(): O(1); merge(): O(n) Realizzazione basata su alberi merge(): O(1); find(): O(n) Algoritmi basati su euristiche di bilanciamento Realizzazione basata su liste + Euristica sul peso Realizzazione basata su alberi + Euristica sul rango Algoritmi finale Alberi + rango + compressione dei percorsi © Alberto Montresor

32 Realizzazione basata su liste
Ogni insieme viene rappresentato con una lista concatenata Il primo oggetto di una lista è il rappresentante dell’insieme Ogni elemento nella lista contiene: un oggetto un puntatore all’elemento successivo un puntatore al rappresentante Può essere visto come un albero di altezza 1 # head c h e b tail © Alberto Montresor

33 Realizzazione basata su liste
L’operazione find(x) richiede tempo O(1) Si restituisce il rappresentante di x L’operazione merge(x,y) è più complessa: Si “appende” la lista che contiene y alla lista che contiene x I puntatori ai rappresentanti della lista “appesa” devono essere modificati Costo nel caso pessimo per n operazioni: O(n2) Costo ammortizzato: O(n) merge(2,1), merge(3,1), merge(4,1), etc. © Alberto Montresor

34 QuickFind: Esempio - merge(h, g)
b f g d z f g d z c h e b © Alberto Montresor

35 Realizzazione basata su alberi (foreste)
Implementazione basata su foresta Si rappresenta ogni insieme tramite un albero radicato Ogni nodo dell'albero contiene l'oggetto un puntatore al padre Il rappresentante è la radice dell'albero La radice ha come padre un puntatore a se stessa Nota: generalmente migliore, non più veloce delle liste nel caso pessimo f c h e d b g © Alberto Montresor

36 Realizzazione basata su alberi
Operazioni e costo find(x) Risale la lista dei padri di x fino a trovare la radice e restituisce la radice come oggetto rappresentante Costo: O(n) nel caso pessimo merge(x,y) Appende l'albero radicato in y ad x Costo: O(1) © Alberto Montresor

37 Realizzazione basata su alberi: Esempio – merge(c, f)
h e d h e f d b b g g © Alberto Montresor

38 Realizzazione basata su alberi: Esempio – merge(c, f)
d e f d g g © Alberto Montresor

39 Realizzazione basata su liste?
Considerazioni Quando usare.... Realizzazione basata su liste? Quando le merge() sono rare e le find() frequenti Realizzazione basate su alberi? Quando le find() sono rare e le merge() frequenti E' importante sapere che esistono tecniche euristiche che permettono di migliorare questi risultati: Fino a operazioni in tempo ammortizzato O(1) per tutte le utilizzazioni pratiche © Alberto Montresor

40 Realizzazione basata su liste: Euristica peso
Una strategia per diminuire il costo dell’operazione merge(): Memorizzare l’informazione sulla lunghezza della lista Appendere la lista più corta a quella più lunga La lunghezza della lista può essere mantenuta in tempo O(1) 4 2 c h e b f g © Alberto Montresor

41 Realizzazione basata su liste: Euristica peso
Una strategia per diminuire il costo dell’operazione merge(): Memorizzare l’informazione sulla lunghezza della lista Appendere la lista più corta a quella più lunga La lunghezza della lista può essere mantenuta in tempo O(1) 6 c h e b f g © Alberto Montresor

42 Realizzazione basata su alberi: Euristica sul rango
Ogni nodo mantiene informazioni sul proprio rango il rango rango[x] di un nodo x è il numero di archi del cammino più lungo fra x e una foglia sua discendente rango ≡ altezza del sottoalbero associato al nodo Unione di due alberi con rango diverso Unione di due alberi con rango uguale f f c + = c c + = c h e d h e f h e d h e f b b d b g b d g © Alberto Montresor

43 Compressione dei cammini
Compressione dei cammini: idea Utilizzata durante le operazioni find(x) L'albero viene modificato in modo che ricerche successive di x possano completare in O(1) Esempio: operazione find(f) b e d f b e d f © Alberto Montresor

44 Compressione dei cammini + rango
Quando si utilizzano entrambe le euristiche: Il rango non è più l'altezza del nodo ... ...ma il limite superiore all'altezza del nodo In altre parole: Le operazioni di compressione dei cammini NON riducono il rango Sarebbe troppo complesso mantenere le informazioni di altezza corrette In ogni caso, non è necessario © Alberto Montresor

45 Realizzazione basata su alberi + rango + compressione dei cammini
© Alberto Montresor

46 Valutiamo ora la complessità di: Liste + Euristica sul peso
Alberi + Euristica sul rango Alberi + Euristica sul rango + Compressione dei cammini Alla lavagna! Ne segue che tutte queste implementazioni (e in particolare l'ultima) sono ampiamente utilizzabili in pratica © Alberto Montresor


Scaricare ppt "Algoritmi e Strutture Dati"

Presentazioni simili


Annunci Google