ALBERO: UN GRAFO PARTICOLARE
GRAFI, OTTIMIZZAZIONE ED APPLICAZIONI
Dr. Gaetano Rossiello,
Dr. Andrea Pazienza,
Dr. Fabio Cassano
24/05/2016
Dottorato in Informatica e Matematica (XXX e XXXI Ciclo)
Prof.ssa Nicoletta Del Buono
Overview
1. Introduzione
2. Alberi Binari
3. Alberi n-ari
4. Alberi di Ricerca
INTRODUZIONE
Introduzione
Un albero è una struttura informatica fondamentale utile per
rappresentare:
Partizioni successive di un insieme in sottoinsiemi
disgiunti
Organizzazioni gerarchiche di dati
Procedimenti decisionali enumerativi
Alberi
Un albero è un particolare tipo di grafo, definito
matematicamente con una coppia
T (N, A)
dove N è un insieme finito di nodi ed A è un insieme di coppie
non ordinate (albero libero) tali che:
il numero di archi è uguale al numero di nodi meno uno:
|A| |N| − 1
T è connesso, ovvero
∀u, v ∈ N ∃ u0, u1, . . . , uk s.t. u u0, v uk
e la coppia ui , ui+1 è un arco di A, per i 0, 1, . . . , k − 1
Alberi radicati
Un albero radicato è ottenuto da un albero libero designando
arbitrariamente un nodo r come radice e ordinando i nodi per
livelli.
Alberi
La radice r è a livello 0 e tutti i nodi u, tali che u, r ∈ A, sono
figli di r e stanno a livello 1 (r è padre). Nodi con lo stesso
padre sono fratelli. Nodi terminali senza figli sono detti foglie.
Un albero ordinato è ottenuto da uno radicato stabilendo un
ordinamento tra nodi allo stesso livello.
Alberi
Se T è un albero ed n e m sono nodi di T si dice che:
m è discendente di n se n è antenato di m cioè se n m
oppure se n è genitore di un antenato di m
una linea di T connette due nodi, uno dei quali è genitore
dell’altro
un cammino in T è la sequenza di linee che unisce due
nodi, uno dei quali è antenato dell’altro: la lunghezza di
un cammino è costituita dal numero di linee che lo
compongono
la altezza di un nodo è la lunghezza del cammino più
lungo da quel nodo ad una foglia
la profondità di un nodo è la lunghezza del cammino dalla
radice a quel nodo
Albero di ordine k
Definiamo un albero di ordine k un albero in cui ogni nodo ha
al massimo k figli
Proprietà degli Alberi
In un albero valgono le sequenti proprietà:
un albero è un grafo aciclico, in cui per ogni nodo c’è un
solo arco entrante (tranne che per la radice che non ne ha
nessuno)
un albero è un grafo debolmente connesso
se esiste un cammino che va da un nodo u ad un altro nodo
v, tale cammino è unico
in un albero esiste un solo cammino che va dalla radice a
qualunque altro nodo
tutti i nodi di un albero T (tranne r) possono essere ripartiti
in insiemi disgiunti ciascuno dei quali individua un albero
(dato un nodo u, i suoi discendenti costituiscono un albero
detto sottoalbero di radice u)
La natura ricorsiva degli alberi
Un albero può essere definito ricorsivamente
un albero è un insieme non vuoto di nodi ai quali sono
associate delle informazioni
tra i nodi esiste un nodo particolare che è la radice (livello
0)
gli altri nodi sono partizionati in sottoinsiemi che sono a
loro volta alberi (livelli successivi)
Vale a dire un albero è



vuoto o costituito da un solo nodo (detto radice)
oppure è una radice cui sono connessi altri alberi
ALBERI BINARI
Alberi Binari
Un albero binario è un grafo orientato che o è vuoto o è
costituito da un solo nodo o è formato da un nodo n (detto
radice) e da due sottoalberi binari, che vengono chiamati
rispettivamente sottoalbero sinistro e sottoalbero destro.
Sono particolari alberi ordinati in cui ogni nodo ha al più due
figli e si fa sempre distinzione tra il figlio sinistro, che viene
prima nell’ordinamento e il figlio destro. Nell’esempio gli
alberi sono etichettati con interi e con caratteri.
Tipi: alberobin, boolean, nodo
Operatori:
CREABINALBERO: ( ) → alberobin
BINALBEROVUOTO: (albero) → boolean
INSBINRADICE: (nodo, albero) → albero
INSFIGLIOSINISTRO: (nodo, albero) → albero
INSFIGLIODESTRO: (nodo, albero) → albero
BINRADICE: (albero) → nodo
BINPADRE: (nodo, albero) → nodo
FIGLIOSINISTRO: (nodo, albero) → nodo
FIGLIODESTRO: (nodo, albero) → nodo
FIGLIOSINISTROVUOTO: (nodo, albero) → boolean
FIGLIODESTROVUOTO: (nodo, albero) → boolean
CANCSOTTOBINALBERO: (nodo, albero) → albero
Algoritmi di visita
Algoritmi che consentono di analizzare tutti i nodi dell’albero
in un ordine definito.
Risultano particolarmente importanti in problemi per i quali,
ad esempio, si debba ricercare in quale nodo o a quale livello è
contenuto in etichetta un valore dato in input oppure quando si
voglia esplorare l’albero per verificarne la profondità.
La visita di un albero consiste nel seguire una rotta di viaggio
che consenta di esaminare ogni nodo dell’albero esattamente
una volta.
Algoritmi di visita in ampiezza (Breadth-First Search)
L’algoritmo di visita in ampiezza (BFS) si applica ad un albero
non vuoto e richiede dapprima la visita della radice dell’albero
e poi procede visitando i nodi per livelli successivi.
Un nodo sul livello i può essere visitato solo se tutti i nodi sul
livello i − 1 sono stati visitati.
Algoritmi di visita in profondità (Depth-First Search)
I più comuni algoritmi di visita in profondità (DFS) sono tre:
visita in pre-ordine: si applica ad un albero non vuoto e
richiede dapprima l’analisi della radice dell’albero e, poi,
la visita, effettuata con lo stesso metodo, dei due
sottoalberi, prima il sinistro, poi il destro
visita in post-ordine: si applica ad un albero non vuoto e
richiede dapprima la visita, effettuata con lo stesso metodo,
dei sottoalberi, prima il sinistro e poi il destro, e, in seguito,
l’analisi della radice dell’albero
visita simmetrica: richiede prima la visita del sottoalbero
sinistro (effettuata sempre con lo stesso metodo), poi
l’analisi della radice, e poi la visita del sottoalbero destro
Visita in pre-ordine
visita in pre-ordine: h a d l o q c p s
Visita in post-ordine
visita in post-ordine: d o q l a p s c h
Visita simmetrica
visita simmetrica: d a o l q h p c s
Visita in ampiezza
visita in ampiezza: h a c d l p s o q
Indovina il giusto algoritmo di visita
Formulazione ricorsiva degli algoritmi di visita
Gli algoritmi si possono facilmente formulare in modo
ricorsivo. Ad esempio:
Visita in preordine l’albero binario T
IF l’albero non è vuoto
analizza la radice di T
visita in preordine il sottoalbero sinistro di T
visita in preordine il sottoalbero destro di T
ENDIF
Applicazioni: Alberi di analisi (Parse Tree)
(3/(x2 ∗ y + 3 ∗ x)) ∗ (z − 1)
Rappresentazioni
Vettore sequenziale
Collegata mediante cursori (array)
Collegata mediante variabili dinamiche
Rappresentazioni: Vettore sequenziale
Radice in prima posizione
Figlio sinistro in posizione 2 ∗ i
Figlio destro in posizione 2 ∗ i + 1
Rappresentazioni: Vettore sequenziale
Problemi della rappresentazione con vettore sequenziale
Vettori sparsi per alberi binari non completi
Dimensione fissa per rappresentare i nodi
Operazioni di inserimento e cancellazione dei nodi
richiede molti shift nel vettore
Rappresentazioni: Collegata mediante cursori
Rappresentazioni: Collegata mediante variabili dinamiche
Ricerca binaria mediante albero binario
ALBERI n-ARI
Alberi n-ari
Un albero è un grafo orientato che o è vuoto oppure ha le
seguenti caratteristiche:
esiste un nodo r, detto radice, senza predecessori, con n
(n > 0) nodi successori a1, a2, . . . , an;
tutti gli altri nodi sono ripartiti in n sottoalberi
mutuamente disgiunti T1, T2, ..., Tn aventi rispettivamente
a1, a2, . . . , an come radice.
L’albero n-ario è un tipo astratto di dati utilizzato per
rappresentare relazioni gerarchiche tra oggetti.
Nella definizione data abbiamo assunto che sui figli di ogni
nodo sia definita una relazione d’ordine (alberi ordinati).
Specifica Sintattica
Tipi: albero, boolean, nodo
Operatori:
CREAALBERO: ( ) → albero
ALBEROVUOTO: (albero) → boolean
INSRADICE: (nodo, albero) → albero
RADICE: (albero) → nodo
PADRE: (nodo, albero) → nodo
FOGLIA: (nodo, albero) → boolean
PRIMOFIGLIO: (nodo, albero) → nodo
ULTIMOFRATELLO: (nodo, albero) → boolean
SUCCFRATELLO: (nodo, albero) → nodo
INSSOTTOALBERO: (nodo, albero, albero) → albero
CANCSOTTOALBERO: (nodo, albero) → albero
Algoritmi di visita
Esistono modi diversi per effettuare una visita corrispondenti
all’ordine con cui si intende seguire la struttura.
Sia T un albero non vuoto di radice r. Se r non è foglia ed ha k
(k > 0) figli, siano T1, T2, . . . , Tk i sottoalberi di T aventi come
radici i figli di r. Gli ordini di visita sono:
previsita (preordine): consiste nell’esaminare r e poi
effettuare la previsita di T1, T2, . . . , Tk;
postvisita (postordine): consiste nel fare prima la
postvisita di T1, T2, . . . , Tk e poi nell’esaminare la radice r;
invisita (ord. simmetrico): consiste nel fare, nell’ordine la
invisita di T1, T2, . . . , Ti, nell’esaminare r, e poi effettuare,
nell’ordine, la invisita di Ti+1, . . . , Tk, per un prefissato
i ≥ 1.
Sia un albero che ha degli interi nei nodi:
La visita in preordine ha l’effetto di visitare i nodi secondo la
sequenza: 5 4 8 9 12 11 3 15 6 21 20
La vista in postordine produce: 8 12 11 3 9 4 15 21 20 6 5
La invisita (i 1) produce: 8 4 12 9 11 3 5 15 21 6 20
Equivalenza di alberi n-ari e binari
Si può trovare una equivalenza ai fini della pre-visita.
In questo modo, è sempre possibile rappresentare un albero
n-ario ordinato T con un albero binario B avente gli stessi nodi
e la stessa radice: in B ogni nodo ha come figlio sinistro il primo
figlio in T e come figlio destro il fratello successivo in T.
Equivalenza di alberi n-ari e binari
Risulta facile notare che le sequenze di nodi esaminati su T e su
B coincidono se T e B sono visitati in previsita.
Rappresentazioni di alberi n-ari
Rappresentazione con vettore di padri
Rappresentazione attraverso liste di figli
Rappresentazione mediante lista PrimoFiglio/fratello
Rappresentazione collegata mediante lista dinamica
Rappresentazione con vettore di padri
Immaginando di numerare i nodi di T da 1 a n, la più semplice
realizzazione (sequenziale) consiste nell’usare un vettore che
contiene, per ogni nodo i (1 ≤ i ≤ n) il cursore al padre.
È facile, così, visitare i nodi lungo percorsi che vanno da foglie a
radice. È, invece, più complesso inserire e cancellare sottoalberi.
Rappresentazione attraverso liste di figli
Comprende:
il vettore dei nodi, in cui, oltre alle eventuali etichette dei
nodi, si memorizza il riferimento iniziale di una lista
associata ad ogni nodo;
una lista per ogni nodo, detta lista dei figli. La lista
associata al generico nodo i contiene tanti elementi quanti
sono i successori di i; ciascun elemento è il riferimento ad
uno dei successori.
Per l’esempio precedente si avrebbe:
Rappresentazione mediante lista PrimoFiglio/fratello
Prevede la gestione di una lista e questo può essere fatto
imponendo che tutti gli alberi condividano un’area comune (ad
esempio un vettore nella realizzazione con cursori) e che ogni
cella contenga esattamente due cursori: uno al primo figlio ed
uno al fratello successivo.
La realizzazione è simile a quella proposta per gli alberi binari
con l’unica differenza che il cursore nel terzo campo punta al
fratello.
Rappresentazione mediante lista PrimoFiglio/fratello
Naturalmente è possibile anche prevedere un cursore al
genitore:
Rappresentazione collegata mediante lista dinamica
Da un punto di vista formale l’albero n-ario può essere
rappresentato mediante lista secondo le seguenti regole:
se l’albero è vuoto la lista che lo rappresenta è vuota;
altrimenti, l’albero è composto da una radice e da k
sottoalberi T1, T2, . . . , Tk e la lista è fatta da k + 1 elementi:
il primo rappresenta la radice, mentre gli altri sono gli
alberi T1, T2, . . . , Tk (con k ≥ 0);
Rappresentazione collegata mediante lista dinamica
Ad esempio, l’albero corrisponde a
Rappresentazione collegata mediante lista dinamica
La rappresentazione con lista dinamica è comunque complessa:
in generale, la radice dell’albero viene memorizzata nel primo
elemento della lista che contiene il riferimento ad una lista di
elementi, uno per ogni sottoalbero.
Ciascuno di questi elementi contiene, a sua volta, il riferimento
iniziale alla lista che rappresenta il corrispondente sottoalbero.
Una possibile realizzazione prevede record e puntatori, ma il
record va inteso con varianti: per esempio, si può prevedere un
record con tre campi, uno per la parte informazione e due per i
puntatori.
Rappresentazione collegata mediante lista dinamica
Per ogni record sarà sempre significativo uno dei campi
puntatore, ma quando l’atomo rappresenta un nodo effettivo
dell’albero sarà utilizzata l’etichetta e un puntatore, quando
rappresenta un atomo "di servizio" saranno utilizzati due
puntatori.
Union-Find
L’MFSet (Merge-Find Set), altrimenti conosciuto come struttura
dati union-find, è una struttura dati derivante dal concetto di
Insieme delle parti, per cui dato un insieme finito di elementi a
volte risulta utile partizionarli in insiemi disgiunti, detti
componenti. È possibile rappresentarlo mediante una foresta
di alberi radicati in cui ciascun albero rappresenta una
componente.
Due operazioni possibili su questa struttura dati:
Ricerca (o trova): determina in quale insieme si trova un
particolare elemento, o se due elementi appartengono allo
stesso insieme;
Unione (o fondi): combina o fonde due insiemi in un unico
insieme.
Realizzazione di MFSet
Le componenti iniziali di MFset sono i nodi. Attraverso
operazioni successive di "fondi e trova" si crea la struttura.
L’operatore fondi combina due alberi nello stesso albero. Si
realizza imponendo che una delle due radici diventi nuovo
figlio dell’altra.
L’operatore trova verifica se due elementi sono nel medesimo
albero. Si realizza accedendo ai nodi contenenti gli elementi e
risalendo da tali nodi, attraverso i padri, fino ad arrivare alle
radici.
Con l’utilizzo di questi operatori è possibile risolvere molti
problemi, come ad esempio l’implementazione dell’algoritmo
di Kruskal.
Realizzazione di MFSet
Applicazioni di alberi n-ari: Rappresentazione del DOM
Il Document Object Model (spesso abbreviato come DOM),
letteralmente modello a oggetti del documento, è una forma di
rappresentazione dei documenti strutturati come modello
orientato agli oggetti.
DOM è lo standard ufficiale per la rappresentazione di
documenti strutturati in maniera da essere neutrali sia per la
lingua che per la piattaforma.
Un classico esempio di albero DOM è quello generato da un
browser web nell’interpretazione di un documento HTML.
Rappresentazione del DOM
Esempio di pagina HTML
<!-- My document -->
<html>
<head>
<title>My Document</title>
</head>
<body>
= Header =
<p>
Paragraph
</p>
</body>
</html>
Rappresentazione del DOM
È da notare che in questo esempio anche i cosiddetti caratteri
blank (spazi, tabulazioni, ecc.) sono considerati elementi
dell’albero, nonostante questi non vengano poi mostrati dal
browser (a meno che non si trovino all’interno di un tag pre).
Rappresentazione del DOM
Nativamente supportato dai browser per modificare gli
elementi di un documento HTML. DOM è un modo per
accedere e aggiornare dinamicamente il contenuto, la struttura
e lo stile dei documenti.
DOM permette di visualizzare un documento ben formato sotto
forma di albero: la maggior parte dei parser e i processori sono
stati sviluppati per usare la struttura ad albero. Questa
implementazione richiede che l’intero contenuto di un
documento venga analizzato e salvato in memoria.
DOM è utilizzato principalmente per recuperare informazioni
da documenti con una strutturazione non standard, cioè dove
gli elementi devono essere trovati in modo casuale.
ALBERI DI RICERCA
Alberi di connessione minimi su grafi
Algoritmo di Kruskal
Algoritmo di Prim
Alcune definizioni
Si definisce taglio (S, V − S) di un grafo non orientato
G (V, E), una partizione di V.
Si dice che un arco (u, v) ∈ E attraversa il taglio (S, V − S) se
una delle due estremità si trova in S e l’altra in V − S
Si dice che un taglio rispetta un insieme A di archi se nessun
arco di A attraversa il taglio.
Un arco è un arco leggero per un taglio se il suo peso è il
minimo fra i pesi degli archi che attraversano il taglio
Teorema dell’arco sicuro
TEOREMA 1:
Sia G (V, E) un grafo connesso, non orientato con una
funzione di peso w a valori reali e definita in E. Sia A un
sottoinsieme di E che è contenuto in qualche albero di
connessione minimio per G; sia (S, V − S) un taglio qualsiasi di
G che rispetta A e sia (u, v) un arco leggero che attraversa
(S, V − S).
Allora l’arco (u, v) è un arco sicuro per A.
Algoritmo di tipo "Greedy" o "Goloso"
Un algoritmo greedy è un algoritmo che cerca di ottenere una
soluzione ottima da un punto di vista globale attraverso la scelta
della soluzione più golosa (o greedy) ad ogni passo locale.
Questa tecnica consente, dove applicabile (infatti non sempre si
arriva ad una soluzione ottima), di trovare soluzioni ottimali
per determinati problemi in un tempo polinomiale.
Algoritmo di Kruskal
L’algoritmo di Kruskal trova un arco sicuro da aggiungere
alla foresta in costruzione scegliendo, fra tutti gli archi che
collegano due alberi qualsiasi nella foresta, un arco (u, v)
di peso minimo.
L’algoritmo di Kruskal è greedy (goloso) perchè ad ogni
passo aggiunge alla alla foresta un arco con il minor peso
possibile.
Sfruttiamo i concetti di FIND e UNION definiti
precedentemente
Algoritmo di Kruskal
ALGORITMO MST DI KRUSKAL (G, w)
A 0
ordina gli archi di G.E in senso non decrescente rispetto
al peso w
FOR ogni arco (u, v) ∈ G.E, preso in ordine di peso non
decrescente
IF FIND(u) FIND(v)
A A ∪ (u, v)
UNION (u, v)
RETURN A
Il tempo di esecuzione dell’algoritmo dipende dalla struttura
dati utilizzata per memorizzare i nodi e i vertici.
Esempio
Algoritmo di Prim
E’ molto simile all’algoritmo di Dijkstra
Si parte da un nodo qualunque
Ad ogni passo viene aggiunto un arco leggero che collega
l’albero analizzato A con un vertice isolato
Algoritmo greedy
Tutti i rami non esplorati vengono inizializzati ad ∞
Algoritmo di Prim
Si sfrutta il concetto di coda di min-priorità Q (basata su un
campo key) dove risiedono tutti i vertici che non si trovano
nell’albero. Per ogni vertice v, il valore v.key rappresenta il
peso minimo di un arco qualsiasi che collega v ad un vertice
nell’albero.
Inizialmente si assegna v.key ∞.
Quando l’algoritmo termina la coda min-priorità Q è vuota.
Algoritmo di Prim
Sia r la radice dell’albero: il nodo di partenza sul grafo.
Considerato un nodo v, allora v.p identifica il padre di v
nell’albero
MST-Prim (G,w, r)
r.key 0
Q G.V
WHILE Q 0
u= EXTRACT-MIN(Q)
FOR ogni v ∈ G.adj[u]
IF v ∈ Q ∧ w(u, v) < v.key
v.p u
v.key w(u, v)
Algoritmo di Prim: Esempio 1
Algoritmo di Prim: Esempio 2
Alberi Binari di ricerca
Un albero binario di ricerca (o BST) è un particolare tipo di
albero binario rappresentato da una struttura dati concatenata
in cui ogni nodo è un oggetto. Ogni nodo ha:
Una chiave k
Attributi puntatori a nodi left, right e parent
Attributi satelliti
Proprietà degli alberi binari di ricerca
Sia x un nodo in un albero binario di ricerca.
Se y è un nodo nel sottoalbero sinistro di x, allora
y.key ≤ x.key
Se y è un nodo nel sottoalbero destro di x, allora y.key ≥ x.key
Attraversamento degli alberi binari di ricerca
La particolare struttura dell’albero binario consente
l’attraversamento dello stesso mediante un algoritmo ricorsivo
sia inorder che preorder e postorder.
Se x è la radice di un sottoalbero di n nodi, la visita inorder(x)
richiede Θ(n)
Interrogazione degli alberi
Gli alberi binari supportano le operazioni di:
Search
Minimum
Maximum
Successor
Predecessor
Search - Ricerca
Sia x la radice dell’albero e k la chiave da cercare:
RECURSIVE TREE-SEARCH(x,k)
IF x nil ∨ k x.key
RETURN x
IF k x.key
RETURN TREE-SEARCH(x.le f t, k)
ELSE RETURN TREE-SEARCH(x.right, k)
In altre parole, sfruttando le proprietà dell’albero, lo si esplora
fino al raggiungimento dell’elemento (se esiste). Questa
operazione richiede O(h) tempo, dove h è l’altezza dell’albero.
Minimum - Ricerca del minimo
Un elemento con chiave minimia può essere sempre trovato, a
partire dalla radice, seguendo i puntatori le f t dei figli a sinistra
fino a quando non si trova il valore nil.
TREE-MINIMUM(x)
WHILE x.le f t nil
x x.le f t
RETURN x
Maximum - Ricerca del massimo
Un elemento con chiave massima può essere sempre trovato, a
partire dalla radice, seguendo i puntatori right dei figli a destra
fino a quando non si trova il valore nil.
TREE-MAXIMUM(x)
WHILE x.right nil
x x.right
RETURN x
Successor - Ricerca del successore
Spesso è importante trovare il successore di un nodo. Se tutte le
chiavi sono distinte, il successore di un nodo x è quello con la
più piccola chiave che è maggiore di x.key.
TREE-SUCCESSOR(x)
IF x.right nil
RETURN TREE-MINIMUM(x)
y x.p
WHILE y nil ∧ x y.right
x y
y y.p
RETURN y
Predecessor - Ricerca del predecessore
Analogamente al punto precedente si trova il predecessore di
un dato nodo.
TREE-PREDECESSOR(x)
IF x.le f t nil
RETURN TREE-MAXIMUM(x)
y x.p
WHILE y nil ∧ x y.le f t
x y
y y.p
RETURN y
Alberi Rosso-Neri
Gli alberi rosso-neri sono dei classici alberi binari di ricerca, con
l’aggiunta di un’informazione relativa al colore del nodo in
analisi.
A livello implementativo, tale informazione si rappresenta con
un bit.
Struttura di un nodo
Ogni nodo ha le seguenti caratteristiche:
color
key
*left
*right
*parent
Se manca un figlio o il padre di un nodo, il corrispondente
puntatore contiene il valore NIL.
Proprietà degli alberi Rosso-Neri
Un albero rosso-nero è approsimativamente sempre bilanciato.
Ha delle importanti proprietà:
1. Ogni nodo o è di colore rosso o di colore nero;
2. La radice è sempre nera;
3. Ogni foglia (NIL) è nera;
4. Se un nodo è rosso, allora i suoi figli sono neri;
5. Per ogni nodo, tutti i cammini semplici che vanno dal nodo
alle foglie sue discendenti contengono lo stesso numero di
nodi neri.
Come e perchè
Questi tipi di alberi sono particolarmente efficaci quando si
implementano strutture dati tipo array associativi o insiemi.
Sono particolarmente utili per le applicazioni real time.
Si definiscono due principali operazioni:
Inserimento
Cancellazione
Rotazione
Rotazione
Inserimento e cancellazione richietono un tempo O(log n);
tuttavia ogni operazione potrebbe violare una delle 5 proprietà
descritte in precedenza.
Per ripristinare le proprietà di un albero che ha subito un
inserimento o una cancellazione si usa metodo della rotazione.
Rotazione: concetto base
Esempio: rotazione a sinistra di x
IPOTESI: il figlio destro di y non è NIL.
La rotazione a sinistra "fa perno" sul collegamento tra x ed y. Il
nodo y diventa la nuova radice del sottoalbero, con x come
figlio sinistro di y e il figlio sinistro di y come figlio destro di x.
Le rotazioni vengono eseguite nel tempo O(1)!
Esempio: rotazione a sinistra di x
Inserimento
L’inserimento all’interno di un albero rosso-nero avviene in un
tempo O(log n). La procedura per l’inserimento è la stessa vista
nel caso di alberi binari, con l’unica accortezza da mantenere:
1. Si assegna T.nil come figli destri e sinistri del nodo
2. Si assegna al nodo il colore ROSSO
3. Si eseguono delle procedure di verifica delle proprietà
degli albero Rosso-Neri
Metodi per il mantenimeto delle proprietà
Ricolorazione: cambiamento dei colori dei nodi figlio e
padre dell’albero
Ristrutturazione: cambiamento opportuno mediante la
rotazione della posizione dei nodi
Ricolorazione
Ricolorazione 2
Ristrutturazione
Esempio
Esempio
References
A. Bertossi e A. Montresor
Algoritmi e Strutture di Dati
CittàStudi, Seconda edizione
C. Demetrescu, I. Finocchi, G. F. Italiano
Algoritmi e Strutture di Dati
McGraw-Hill
Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest,
Clifford Stein
Introduzione agli algoritmi e strutture dati
McGraw-Hill, Terza edizione

More Related Content

DOCX
question and answer about quality control
PPT
Ops management lecture 6 quality tools & techniques
PPT
Episode 24 : Project Quality Management
PPT
4-CMMI Process Area Components
PPT
Historia de la computadora
DOC
Operations Manager Responsibilities
PPTX
Introduction to 3G technology
PPTX
Quality management
question and answer about quality control
Ops management lecture 6 quality tools & techniques
Episode 24 : Project Quality Management
4-CMMI Process Area Components
Historia de la computadora
Operations Manager Responsibilities
Introduction to 3G technology
Quality management

More from Andrea Pazienza (7)

PDF
Mining Arguments from Online Debating Systems
PDF
Synthesis of Argumentation Graphs by Matrix Factorization
PDF
Constructing and Evaluating Bipolar Weighted Argumentation Frameworks for Onl...
PDF
Clustering Underlying Stock Trends via NMF
PDF
An Authority Degree-based Evaluation Strategy for Abstract Argumentation Fram...
PDF
An Abstract Argumentation-based Strategy for Reading Order Detection
PDF
Empowered Negative Specialization in Inductive Logic Programming
Mining Arguments from Online Debating Systems
Synthesis of Argumentation Graphs by Matrix Factorization
Constructing and Evaluating Bipolar Weighted Argumentation Frameworks for Onl...
Clustering Underlying Stock Trends via NMF
An Authority Degree-based Evaluation Strategy for Abstract Argumentation Fram...
An Abstract Argumentation-based Strategy for Reading Order Detection
Empowered Negative Specialization in Inductive Logic Programming
Ad

Recently uploaded (11)

PDF
PRESENTAZIONE PROGETTO CCCI IN ITALIANO .pdf
PDF
Critico_o_creativo_Approcci_al_testo_let.pdf
PDF
NGÂN HÀNG CÂU HỎI TÁCH CHỌN LỌC THEO CHUYÊN ĐỀ TỪ ĐỀ THI THỬ TN THPT 2025 TIẾ...
PDF
NGÂN HÀNG CÂU HỎI TÁCH CHỌN LỌC THEO CHUYÊN ĐỀ TỪ ĐỀ THI THỬ TN THPT 2025 TIẾ...
PPTX
San Giovanni Eudes, 1601 – 1680, sacerdote e fondatore francese.pptx
PPTX
Santa Rosa da Lima, Vergine, Penitente, Terziaria Domenicana 1586-1617.pptx
PDF
NGÂN HÀNG CÂU HỎI TÁCH CHỌN LỌC THEO CHUYÊN ĐỀ TỪ ĐỀ THI THỬ TN THPT 2025 TIẾ...
PDF
Libro per insegnare di Balboni: Lingue_e_linguaggi.pdf
PDF
Presentazione di Chimica sui Coloranti Alimentari
PDF
NGÂN HÀNG CÂU HỎI TÁCH CHỌN LỌC THEO CHUYÊN ĐỀ TỪ ĐỀ THI THỬ TN THPT 2025 TIẾ...
PDF
Presentazione educazione finanziaria e informazione.pdf
PRESENTAZIONE PROGETTO CCCI IN ITALIANO .pdf
Critico_o_creativo_Approcci_al_testo_let.pdf
NGÂN HÀNG CÂU HỎI TÁCH CHỌN LỌC THEO CHUYÊN ĐỀ TỪ ĐỀ THI THỬ TN THPT 2025 TIẾ...
NGÂN HÀNG CÂU HỎI TÁCH CHỌN LỌC THEO CHUYÊN ĐỀ TỪ ĐỀ THI THỬ TN THPT 2025 TIẾ...
San Giovanni Eudes, 1601 – 1680, sacerdote e fondatore francese.pptx
Santa Rosa da Lima, Vergine, Penitente, Terziaria Domenicana 1586-1617.pptx
NGÂN HÀNG CÂU HỎI TÁCH CHỌN LỌC THEO CHUYÊN ĐỀ TỪ ĐỀ THI THỬ TN THPT 2025 TIẾ...
Libro per insegnare di Balboni: Lingue_e_linguaggi.pdf
Presentazione di Chimica sui Coloranti Alimentari
NGÂN HÀNG CÂU HỎI TÁCH CHỌN LỌC THEO CHUYÊN ĐỀ TỪ ĐỀ THI THỬ TN THPT 2025 TIẾ...
Presentazione educazione finanziaria e informazione.pdf
Ad

Albero: un Grafo particolare

  • 1. ALBERO: UN GRAFO PARTICOLARE GRAFI, OTTIMIZZAZIONE ED APPLICAZIONI Dr. Gaetano Rossiello, Dr. Andrea Pazienza, Dr. Fabio Cassano 24/05/2016 Dottorato in Informatica e Matematica (XXX e XXXI Ciclo) Prof.ssa Nicoletta Del Buono
  • 2. Overview 1. Introduzione 2. Alberi Binari 3. Alberi n-ari 4. Alberi di Ricerca
  • 4. Introduzione Un albero è una struttura informatica fondamentale utile per rappresentare: Partizioni successive di un insieme in sottoinsiemi disgiunti Organizzazioni gerarchiche di dati Procedimenti decisionali enumerativi
  • 5. Alberi Un albero è un particolare tipo di grafo, definito matematicamente con una coppia T (N, A) dove N è un insieme finito di nodi ed A è un insieme di coppie non ordinate (albero libero) tali che: il numero di archi è uguale al numero di nodi meno uno: |A| |N| − 1 T è connesso, ovvero ∀u, v ∈ N ∃ u0, u1, . . . , uk s.t. u u0, v uk e la coppia ui , ui+1 è un arco di A, per i 0, 1, . . . , k − 1
  • 6. Alberi radicati Un albero radicato è ottenuto da un albero libero designando arbitrariamente un nodo r come radice e ordinando i nodi per livelli.
  • 7. Alberi La radice r è a livello 0 e tutti i nodi u, tali che u, r ∈ A, sono figli di r e stanno a livello 1 (r è padre). Nodi con lo stesso padre sono fratelli. Nodi terminali senza figli sono detti foglie. Un albero ordinato è ottenuto da uno radicato stabilendo un ordinamento tra nodi allo stesso livello.
  • 8. Alberi Se T è un albero ed n e m sono nodi di T si dice che: m è discendente di n se n è antenato di m cioè se n m oppure se n è genitore di un antenato di m una linea di T connette due nodi, uno dei quali è genitore dell’altro un cammino in T è la sequenza di linee che unisce due nodi, uno dei quali è antenato dell’altro: la lunghezza di un cammino è costituita dal numero di linee che lo compongono la altezza di un nodo è la lunghezza del cammino più lungo da quel nodo ad una foglia la profondità di un nodo è la lunghezza del cammino dalla radice a quel nodo
  • 9. Albero di ordine k Definiamo un albero di ordine k un albero in cui ogni nodo ha al massimo k figli
  • 10. Proprietà degli Alberi In un albero valgono le sequenti proprietà: un albero è un grafo aciclico, in cui per ogni nodo c’è un solo arco entrante (tranne che per la radice che non ne ha nessuno) un albero è un grafo debolmente connesso se esiste un cammino che va da un nodo u ad un altro nodo v, tale cammino è unico in un albero esiste un solo cammino che va dalla radice a qualunque altro nodo tutti i nodi di un albero T (tranne r) possono essere ripartiti in insiemi disgiunti ciascuno dei quali individua un albero (dato un nodo u, i suoi discendenti costituiscono un albero detto sottoalbero di radice u)
  • 11. La natura ricorsiva degli alberi Un albero può essere definito ricorsivamente un albero è un insieme non vuoto di nodi ai quali sono associate delle informazioni tra i nodi esiste un nodo particolare che è la radice (livello 0) gli altri nodi sono partizionati in sottoinsiemi che sono a loro volta alberi (livelli successivi) Vale a dire un albero è    vuoto o costituito da un solo nodo (detto radice) oppure è una radice cui sono connessi altri alberi
  • 13. Alberi Binari Un albero binario è un grafo orientato che o è vuoto o è costituito da un solo nodo o è formato da un nodo n (detto radice) e da due sottoalberi binari, che vengono chiamati rispettivamente sottoalbero sinistro e sottoalbero destro. Sono particolari alberi ordinati in cui ogni nodo ha al più due figli e si fa sempre distinzione tra il figlio sinistro, che viene prima nell’ordinamento e il figlio destro. Nell’esempio gli alberi sono etichettati con interi e con caratteri.
  • 14. Tipi: alberobin, boolean, nodo Operatori: CREABINALBERO: ( ) → alberobin BINALBEROVUOTO: (albero) → boolean INSBINRADICE: (nodo, albero) → albero INSFIGLIOSINISTRO: (nodo, albero) → albero INSFIGLIODESTRO: (nodo, albero) → albero BINRADICE: (albero) → nodo BINPADRE: (nodo, albero) → nodo FIGLIOSINISTRO: (nodo, albero) → nodo FIGLIODESTRO: (nodo, albero) → nodo FIGLIOSINISTROVUOTO: (nodo, albero) → boolean FIGLIODESTROVUOTO: (nodo, albero) → boolean CANCSOTTOBINALBERO: (nodo, albero) → albero
  • 15. Algoritmi di visita Algoritmi che consentono di analizzare tutti i nodi dell’albero in un ordine definito. Risultano particolarmente importanti in problemi per i quali, ad esempio, si debba ricercare in quale nodo o a quale livello è contenuto in etichetta un valore dato in input oppure quando si voglia esplorare l’albero per verificarne la profondità. La visita di un albero consiste nel seguire una rotta di viaggio che consenta di esaminare ogni nodo dell’albero esattamente una volta.
  • 16. Algoritmi di visita in ampiezza (Breadth-First Search) L’algoritmo di visita in ampiezza (BFS) si applica ad un albero non vuoto e richiede dapprima la visita della radice dell’albero e poi procede visitando i nodi per livelli successivi. Un nodo sul livello i può essere visitato solo se tutti i nodi sul livello i − 1 sono stati visitati.
  • 17. Algoritmi di visita in profondità (Depth-First Search) I più comuni algoritmi di visita in profondità (DFS) sono tre: visita in pre-ordine: si applica ad un albero non vuoto e richiede dapprima l’analisi della radice dell’albero e, poi, la visita, effettuata con lo stesso metodo, dei due sottoalberi, prima il sinistro, poi il destro visita in post-ordine: si applica ad un albero non vuoto e richiede dapprima la visita, effettuata con lo stesso metodo, dei sottoalberi, prima il sinistro e poi il destro, e, in seguito, l’analisi della radice dell’albero visita simmetrica: richiede prima la visita del sottoalbero sinistro (effettuata sempre con lo stesso metodo), poi l’analisi della radice, e poi la visita del sottoalbero destro
  • 18. Visita in pre-ordine visita in pre-ordine: h a d l o q c p s
  • 19. Visita in post-ordine visita in post-ordine: d o q l a p s c h
  • 21. Visita in ampiezza visita in ampiezza: h a c d l p s o q
  • 22. Indovina il giusto algoritmo di visita
  • 23. Formulazione ricorsiva degli algoritmi di visita Gli algoritmi si possono facilmente formulare in modo ricorsivo. Ad esempio: Visita in preordine l’albero binario T IF l’albero non è vuoto analizza la radice di T visita in preordine il sottoalbero sinistro di T visita in preordine il sottoalbero destro di T ENDIF
  • 24. Applicazioni: Alberi di analisi (Parse Tree) (3/(x2 ∗ y + 3 ∗ x)) ∗ (z − 1)
  • 25. Rappresentazioni Vettore sequenziale Collegata mediante cursori (array) Collegata mediante variabili dinamiche
  • 26. Rappresentazioni: Vettore sequenziale Radice in prima posizione Figlio sinistro in posizione 2 ∗ i Figlio destro in posizione 2 ∗ i + 1
  • 27. Rappresentazioni: Vettore sequenziale Problemi della rappresentazione con vettore sequenziale Vettori sparsi per alberi binari non completi Dimensione fissa per rappresentare i nodi Operazioni di inserimento e cancellazione dei nodi richiede molti shift nel vettore
  • 30. Ricerca binaria mediante albero binario
  • 32. Alberi n-ari Un albero è un grafo orientato che o è vuoto oppure ha le seguenti caratteristiche: esiste un nodo r, detto radice, senza predecessori, con n (n > 0) nodi successori a1, a2, . . . , an; tutti gli altri nodi sono ripartiti in n sottoalberi mutuamente disgiunti T1, T2, ..., Tn aventi rispettivamente a1, a2, . . . , an come radice. L’albero n-ario è un tipo astratto di dati utilizzato per rappresentare relazioni gerarchiche tra oggetti. Nella definizione data abbiamo assunto che sui figli di ogni nodo sia definita una relazione d’ordine (alberi ordinati).
  • 33. Specifica Sintattica Tipi: albero, boolean, nodo Operatori: CREAALBERO: ( ) → albero ALBEROVUOTO: (albero) → boolean INSRADICE: (nodo, albero) → albero RADICE: (albero) → nodo PADRE: (nodo, albero) → nodo FOGLIA: (nodo, albero) → boolean PRIMOFIGLIO: (nodo, albero) → nodo ULTIMOFRATELLO: (nodo, albero) → boolean SUCCFRATELLO: (nodo, albero) → nodo INSSOTTOALBERO: (nodo, albero, albero) → albero CANCSOTTOALBERO: (nodo, albero) → albero
  • 34. Algoritmi di visita Esistono modi diversi per effettuare una visita corrispondenti all’ordine con cui si intende seguire la struttura. Sia T un albero non vuoto di radice r. Se r non è foglia ed ha k (k > 0) figli, siano T1, T2, . . . , Tk i sottoalberi di T aventi come radici i figli di r. Gli ordini di visita sono: previsita (preordine): consiste nell’esaminare r e poi effettuare la previsita di T1, T2, . . . , Tk; postvisita (postordine): consiste nel fare prima la postvisita di T1, T2, . . . , Tk e poi nell’esaminare la radice r; invisita (ord. simmetrico): consiste nel fare, nell’ordine la invisita di T1, T2, . . . , Ti, nell’esaminare r, e poi effettuare, nell’ordine, la invisita di Ti+1, . . . , Tk, per un prefissato i ≥ 1.
  • 35. Sia un albero che ha degli interi nei nodi: La visita in preordine ha l’effetto di visitare i nodi secondo la sequenza: 5 4 8 9 12 11 3 15 6 21 20 La vista in postordine produce: 8 12 11 3 9 4 15 21 20 6 5 La invisita (i 1) produce: 8 4 12 9 11 3 5 15 21 6 20
  • 36. Equivalenza di alberi n-ari e binari Si può trovare una equivalenza ai fini della pre-visita. In questo modo, è sempre possibile rappresentare un albero n-ario ordinato T con un albero binario B avente gli stessi nodi e la stessa radice: in B ogni nodo ha come figlio sinistro il primo figlio in T e come figlio destro il fratello successivo in T.
  • 37. Equivalenza di alberi n-ari e binari Risulta facile notare che le sequenze di nodi esaminati su T e su B coincidono se T e B sono visitati in previsita.
  • 38. Rappresentazioni di alberi n-ari Rappresentazione con vettore di padri Rappresentazione attraverso liste di figli Rappresentazione mediante lista PrimoFiglio/fratello Rappresentazione collegata mediante lista dinamica
  • 39. Rappresentazione con vettore di padri Immaginando di numerare i nodi di T da 1 a n, la più semplice realizzazione (sequenziale) consiste nell’usare un vettore che contiene, per ogni nodo i (1 ≤ i ≤ n) il cursore al padre. È facile, così, visitare i nodi lungo percorsi che vanno da foglie a radice. È, invece, più complesso inserire e cancellare sottoalberi.
  • 40. Rappresentazione attraverso liste di figli Comprende: il vettore dei nodi, in cui, oltre alle eventuali etichette dei nodi, si memorizza il riferimento iniziale di una lista associata ad ogni nodo; una lista per ogni nodo, detta lista dei figli. La lista associata al generico nodo i contiene tanti elementi quanti sono i successori di i; ciascun elemento è il riferimento ad uno dei successori. Per l’esempio precedente si avrebbe:
  • 41. Rappresentazione mediante lista PrimoFiglio/fratello Prevede la gestione di una lista e questo può essere fatto imponendo che tutti gli alberi condividano un’area comune (ad esempio un vettore nella realizzazione con cursori) e che ogni cella contenga esattamente due cursori: uno al primo figlio ed uno al fratello successivo. La realizzazione è simile a quella proposta per gli alberi binari con l’unica differenza che il cursore nel terzo campo punta al fratello.
  • 42. Rappresentazione mediante lista PrimoFiglio/fratello Naturalmente è possibile anche prevedere un cursore al genitore:
  • 43. Rappresentazione collegata mediante lista dinamica Da un punto di vista formale l’albero n-ario può essere rappresentato mediante lista secondo le seguenti regole: se l’albero è vuoto la lista che lo rappresenta è vuota; altrimenti, l’albero è composto da una radice e da k sottoalberi T1, T2, . . . , Tk e la lista è fatta da k + 1 elementi: il primo rappresenta la radice, mentre gli altri sono gli alberi T1, T2, . . . , Tk (con k ≥ 0);
  • 44. Rappresentazione collegata mediante lista dinamica Ad esempio, l’albero corrisponde a
  • 45. Rappresentazione collegata mediante lista dinamica La rappresentazione con lista dinamica è comunque complessa: in generale, la radice dell’albero viene memorizzata nel primo elemento della lista che contiene il riferimento ad una lista di elementi, uno per ogni sottoalbero. Ciascuno di questi elementi contiene, a sua volta, il riferimento iniziale alla lista che rappresenta il corrispondente sottoalbero. Una possibile realizzazione prevede record e puntatori, ma il record va inteso con varianti: per esempio, si può prevedere un record con tre campi, uno per la parte informazione e due per i puntatori.
  • 46. Rappresentazione collegata mediante lista dinamica Per ogni record sarà sempre significativo uno dei campi puntatore, ma quando l’atomo rappresenta un nodo effettivo dell’albero sarà utilizzata l’etichetta e un puntatore, quando rappresenta un atomo "di servizio" saranno utilizzati due puntatori.
  • 47. Union-Find L’MFSet (Merge-Find Set), altrimenti conosciuto come struttura dati union-find, è una struttura dati derivante dal concetto di Insieme delle parti, per cui dato un insieme finito di elementi a volte risulta utile partizionarli in insiemi disgiunti, detti componenti. È possibile rappresentarlo mediante una foresta di alberi radicati in cui ciascun albero rappresenta una componente. Due operazioni possibili su questa struttura dati: Ricerca (o trova): determina in quale insieme si trova un particolare elemento, o se due elementi appartengono allo stesso insieme; Unione (o fondi): combina o fonde due insiemi in un unico insieme.
  • 48. Realizzazione di MFSet Le componenti iniziali di MFset sono i nodi. Attraverso operazioni successive di "fondi e trova" si crea la struttura. L’operatore fondi combina due alberi nello stesso albero. Si realizza imponendo che una delle due radici diventi nuovo figlio dell’altra. L’operatore trova verifica se due elementi sono nel medesimo albero. Si realizza accedendo ai nodi contenenti gli elementi e risalendo da tali nodi, attraverso i padri, fino ad arrivare alle radici. Con l’utilizzo di questi operatori è possibile risolvere molti problemi, come ad esempio l’implementazione dell’algoritmo di Kruskal.
  • 50. Applicazioni di alberi n-ari: Rappresentazione del DOM Il Document Object Model (spesso abbreviato come DOM), letteralmente modello a oggetti del documento, è una forma di rappresentazione dei documenti strutturati come modello orientato agli oggetti. DOM è lo standard ufficiale per la rappresentazione di documenti strutturati in maniera da essere neutrali sia per la lingua che per la piattaforma. Un classico esempio di albero DOM è quello generato da un browser web nell’interpretazione di un documento HTML.
  • 51. Rappresentazione del DOM Esempio di pagina HTML <!-- My document --> <html> <head> <title>My Document</title> </head> <body> = Header = <p> Paragraph </p> </body> </html>
  • 52. Rappresentazione del DOM È da notare che in questo esempio anche i cosiddetti caratteri blank (spazi, tabulazioni, ecc.) sono considerati elementi dell’albero, nonostante questi non vengano poi mostrati dal browser (a meno che non si trovino all’interno di un tag pre).
  • 53. Rappresentazione del DOM Nativamente supportato dai browser per modificare gli elementi di un documento HTML. DOM è un modo per accedere e aggiornare dinamicamente il contenuto, la struttura e lo stile dei documenti. DOM permette di visualizzare un documento ben formato sotto forma di albero: la maggior parte dei parser e i processori sono stati sviluppati per usare la struttura ad albero. Questa implementazione richiede che l’intero contenuto di un documento venga analizzato e salvato in memoria. DOM è utilizzato principalmente per recuperare informazioni da documenti con una strutturazione non standard, cioè dove gli elementi devono essere trovati in modo casuale.
  • 55. Alberi di connessione minimi su grafi Algoritmo di Kruskal Algoritmo di Prim
  • 56. Alcune definizioni Si definisce taglio (S, V − S) di un grafo non orientato G (V, E), una partizione di V. Si dice che un arco (u, v) ∈ E attraversa il taglio (S, V − S) se una delle due estremità si trova in S e l’altra in V − S Si dice che un taglio rispetta un insieme A di archi se nessun arco di A attraversa il taglio. Un arco è un arco leggero per un taglio se il suo peso è il minimo fra i pesi degli archi che attraversano il taglio
  • 57. Teorema dell’arco sicuro TEOREMA 1: Sia G (V, E) un grafo connesso, non orientato con una funzione di peso w a valori reali e definita in E. Sia A un sottoinsieme di E che è contenuto in qualche albero di connessione minimio per G; sia (S, V − S) un taglio qualsiasi di G che rispetta A e sia (u, v) un arco leggero che attraversa (S, V − S). Allora l’arco (u, v) è un arco sicuro per A.
  • 58. Algoritmo di tipo "Greedy" o "Goloso" Un algoritmo greedy è un algoritmo che cerca di ottenere una soluzione ottima da un punto di vista globale attraverso la scelta della soluzione più golosa (o greedy) ad ogni passo locale. Questa tecnica consente, dove applicabile (infatti non sempre si arriva ad una soluzione ottima), di trovare soluzioni ottimali per determinati problemi in un tempo polinomiale.
  • 59. Algoritmo di Kruskal L’algoritmo di Kruskal trova un arco sicuro da aggiungere alla foresta in costruzione scegliendo, fra tutti gli archi che collegano due alberi qualsiasi nella foresta, un arco (u, v) di peso minimo. L’algoritmo di Kruskal è greedy (goloso) perchè ad ogni passo aggiunge alla alla foresta un arco con il minor peso possibile. Sfruttiamo i concetti di FIND e UNION definiti precedentemente
  • 60. Algoritmo di Kruskal ALGORITMO MST DI KRUSKAL (G, w) A 0 ordina gli archi di G.E in senso non decrescente rispetto al peso w FOR ogni arco (u, v) ∈ G.E, preso in ordine di peso non decrescente IF FIND(u) FIND(v) A A ∪ (u, v) UNION (u, v) RETURN A Il tempo di esecuzione dell’algoritmo dipende dalla struttura dati utilizzata per memorizzare i nodi e i vertici.
  • 62. Algoritmo di Prim E’ molto simile all’algoritmo di Dijkstra Si parte da un nodo qualunque Ad ogni passo viene aggiunto un arco leggero che collega l’albero analizzato A con un vertice isolato Algoritmo greedy Tutti i rami non esplorati vengono inizializzati ad ∞
  • 63. Algoritmo di Prim Si sfrutta il concetto di coda di min-priorità Q (basata su un campo key) dove risiedono tutti i vertici che non si trovano nell’albero. Per ogni vertice v, il valore v.key rappresenta il peso minimo di un arco qualsiasi che collega v ad un vertice nell’albero. Inizialmente si assegna v.key ∞. Quando l’algoritmo termina la coda min-priorità Q è vuota.
  • 64. Algoritmo di Prim Sia r la radice dell’albero: il nodo di partenza sul grafo. Considerato un nodo v, allora v.p identifica il padre di v nell’albero MST-Prim (G,w, r) r.key 0 Q G.V WHILE Q 0 u= EXTRACT-MIN(Q) FOR ogni v ∈ G.adj[u] IF v ∈ Q ∧ w(u, v) < v.key v.p u v.key w(u, v)
  • 65. Algoritmo di Prim: Esempio 1
  • 66. Algoritmo di Prim: Esempio 2
  • 67. Alberi Binari di ricerca Un albero binario di ricerca (o BST) è un particolare tipo di albero binario rappresentato da una struttura dati concatenata in cui ogni nodo è un oggetto. Ogni nodo ha: Una chiave k Attributi puntatori a nodi left, right e parent Attributi satelliti
  • 68. Proprietà degli alberi binari di ricerca Sia x un nodo in un albero binario di ricerca. Se y è un nodo nel sottoalbero sinistro di x, allora y.key ≤ x.key Se y è un nodo nel sottoalbero destro di x, allora y.key ≥ x.key
  • 69. Attraversamento degli alberi binari di ricerca La particolare struttura dell’albero binario consente l’attraversamento dello stesso mediante un algoritmo ricorsivo sia inorder che preorder e postorder. Se x è la radice di un sottoalbero di n nodi, la visita inorder(x) richiede Θ(n)
  • 70. Interrogazione degli alberi Gli alberi binari supportano le operazioni di: Search Minimum Maximum Successor Predecessor
  • 71. Search - Ricerca Sia x la radice dell’albero e k la chiave da cercare: RECURSIVE TREE-SEARCH(x,k) IF x nil ∨ k x.key RETURN x IF k x.key RETURN TREE-SEARCH(x.le f t, k) ELSE RETURN TREE-SEARCH(x.right, k) In altre parole, sfruttando le proprietà dell’albero, lo si esplora fino al raggiungimento dell’elemento (se esiste). Questa operazione richiede O(h) tempo, dove h è l’altezza dell’albero.
  • 72. Minimum - Ricerca del minimo Un elemento con chiave minimia può essere sempre trovato, a partire dalla radice, seguendo i puntatori le f t dei figli a sinistra fino a quando non si trova il valore nil. TREE-MINIMUM(x) WHILE x.le f t nil x x.le f t RETURN x
  • 73. Maximum - Ricerca del massimo Un elemento con chiave massima può essere sempre trovato, a partire dalla radice, seguendo i puntatori right dei figli a destra fino a quando non si trova il valore nil. TREE-MAXIMUM(x) WHILE x.right nil x x.right RETURN x
  • 74. Successor - Ricerca del successore Spesso è importante trovare il successore di un nodo. Se tutte le chiavi sono distinte, il successore di un nodo x è quello con la più piccola chiave che è maggiore di x.key. TREE-SUCCESSOR(x) IF x.right nil RETURN TREE-MINIMUM(x) y x.p WHILE y nil ∧ x y.right x y y y.p RETURN y
  • 75. Predecessor - Ricerca del predecessore Analogamente al punto precedente si trova il predecessore di un dato nodo. TREE-PREDECESSOR(x) IF x.le f t nil RETURN TREE-MAXIMUM(x) y x.p WHILE y nil ∧ x y.le f t x y y y.p RETURN y
  • 76. Alberi Rosso-Neri Gli alberi rosso-neri sono dei classici alberi binari di ricerca, con l’aggiunta di un’informazione relativa al colore del nodo in analisi. A livello implementativo, tale informazione si rappresenta con un bit.
  • 77. Struttura di un nodo Ogni nodo ha le seguenti caratteristiche: color key *left *right *parent Se manca un figlio o il padre di un nodo, il corrispondente puntatore contiene il valore NIL.
  • 78. Proprietà degli alberi Rosso-Neri Un albero rosso-nero è approsimativamente sempre bilanciato. Ha delle importanti proprietà: 1. Ogni nodo o è di colore rosso o di colore nero; 2. La radice è sempre nera; 3. Ogni foglia (NIL) è nera; 4. Se un nodo è rosso, allora i suoi figli sono neri; 5. Per ogni nodo, tutti i cammini semplici che vanno dal nodo alle foglie sue discendenti contengono lo stesso numero di nodi neri.
  • 79. Come e perchè Questi tipi di alberi sono particolarmente efficaci quando si implementano strutture dati tipo array associativi o insiemi. Sono particolarmente utili per le applicazioni real time. Si definiscono due principali operazioni: Inserimento Cancellazione Rotazione
  • 80. Rotazione Inserimento e cancellazione richietono un tempo O(log n); tuttavia ogni operazione potrebbe violare una delle 5 proprietà descritte in precedenza. Per ripristinare le proprietà di un albero che ha subito un inserimento o una cancellazione si usa metodo della rotazione.
  • 82. Esempio: rotazione a sinistra di x IPOTESI: il figlio destro di y non è NIL. La rotazione a sinistra "fa perno" sul collegamento tra x ed y. Il nodo y diventa la nuova radice del sottoalbero, con x come figlio sinistro di y e il figlio sinistro di y come figlio destro di x. Le rotazioni vengono eseguite nel tempo O(1)!
  • 83. Esempio: rotazione a sinistra di x
  • 84. Inserimento L’inserimento all’interno di un albero rosso-nero avviene in un tempo O(log n). La procedura per l’inserimento è la stessa vista nel caso di alberi binari, con l’unica accortezza da mantenere: 1. Si assegna T.nil come figli destri e sinistri del nodo 2. Si assegna al nodo il colore ROSSO 3. Si eseguono delle procedure di verifica delle proprietà degli albero Rosso-Neri
  • 85. Metodi per il mantenimeto delle proprietà Ricolorazione: cambiamento dei colori dei nodi figlio e padre dell’albero Ristrutturazione: cambiamento opportuno mediante la rotazione della posizione dei nodi
  • 91. References A. Bertossi e A. Montresor Algoritmi e Strutture di Dati CittàStudi, Seconda edizione C. Demetrescu, I. Finocchi, G. F. Italiano Algoritmi e Strutture di Dati McGraw-Hill Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein Introduzione agli algoritmi e strutture dati McGraw-Hill, Terza edizione