Strutture dati
Strutture dati
Tipi di dato astratti
(strutture dati dinamiche)
q
Strutture dati elementari
n
n
n
q
Alberi
n
Organizzazione sistematica dei
dati e del loro accesso
n
n
n
q
Tipo di dato astratto
r
Tipo di dato astratto o ADT (Abstract Data Type):
insieme di oggetti e insieme di operazioni definite su
di esso
r Es.: lista con operazioni di inserimento e
cancellazione
r Attenzione: l’ADT specifica cosa fa ogni operazione,
non come
r In Java:
o Rappresentazione con interfaccia
o Implementazione con classe
Tipo di dato Lista
n
n
n
Insieme di elementi tra i quali è definito un
ordinamento totale.
Numerose varianti
Ammette (almeno) le operazioni seguenti:
q
q
q
q
n
cons(elem): inserisce elem in testa alla lista
cdr(): elimina l’ elemento in testa alla lista
car(): restituisce l’ elemento in testa alla lista senza
eliminarlo
null(): verifica se la lista e’ vuota
Nelle implementazioni (es. Java) sono spesso
presenti altre operazioni
q
Liste
Stack (pile)
Code
Alberi binari
Alberi di ricerca (BST)
Alberi bilanciati (AVL)
B-tree (gestione memoria secondaria)
Grafi
Strutture dati
Tipi di dato astratti
(strutture dati dinamiche)
q
Strutture dati elementari
n
n
n
q
Alberi
n
n
n
n
q
Liste
Stack (pile)
Code
Alberi binari
Alberi di ricerca (BST)
Alberi bilanciati (AVL)
B-tree (gestione memoria secondaria)
Grafi
Liste
n
n
n
si usa quando è necessario scandire un
insieme di oggetti in modo sequenziale
è vantaggiosa quando sono previste frequenti
operazioni di cancellazione o inserzioni
lo svantaggio sta nel fatto che si può
accedere ad un elemento di posizione i solo
dopo aver acceduto a tutti gli i-1 elementi
precedenti
cons(elem, i), remove(i), get(i)
1
Implementazione delle liste
Implementazione con array
r
Occorre conoscere la
dimensione max della
lista
r Può portare a spreco di
memoria
Array
n
q
Si usa un array in memoria
Strutture collegate
n
q
Ogni elemento contiene un riferimento al
successivo
Costo delle principali
operazioni:
n
q
q
q
A0 A1 A2
AN-3 AN-2 AN-1
cons: O(n) (caso
peggiore: elemento in
prima posizione)
cdr: O(n), (caso
peggiore: primo
elemento)
car: O(1)
Elemento non usato
Inserimento in pos. 2
Altri tipi di lista
Implementazione con strutture collegate
n
Efficienza
q
q
n
cons, remove: O(i) (bisogna trovare la posizione
dell’elemento da inserire/rimuovere). O(1) per
inserimenti/cancellazioni in prima posizione
get: O(i) (posizione dell’elemento cercato)
A0
r
A0
A1
Ai
Lista doppia: consente una scansione in entrambe le
direzioni
AN
A1
Ai
AN
Lista circolare: consente di rappresentare strutture in cui
l’ordinamento è mod N
A0
A1
Ai
AN
Inserimento in pos. 1
Strutture dati
Tipi di dato astratti
(strutture dati dinamiche)
q
Strutture dati elementari
n
n
n
q
n
Lista nella quale inserimenti e cancellazioni avvengono solo
in testa (disciplina LIFO).
n
Operazioni sempre presenti
q
Liste
Stack (pile)
Code
n
n
n
q
q
Alberi binari
Alberi di ricerca (BST)
Alberi bilanciati (AVL)
B-tree (gestione memoria secondaria)
Grafi
push(el): inserisce l'elemento specificato da el in cima alla
pila
Alberi
n
q
Tipo astratto Pila
pop(): elimina l'elemento in cima alla pila
top(): restituisce l'elemento in cima alla pila senza cancellarlo
dalla lista
q
n
isEmpty(): verifica se la pila è vuota
Altre operazioni
q
clear(): elimina tutti gli elementi dalla pila
2
Implementazione del tipo Pila
Strutture dati
Tipi di dato astratti
(strutture dati dinamiche)
r Realizzazione tramite Array
q
Ai
Strutture dati elementari
n
top = i
n
A1
A0
n
q
Alberi
n
r Liste: realizzazione tramite lista concatenata
n
n
top
n
Start
q
A0
A1
Ai
Liste
Stack (pile)
Code
Alberi binari
Alberi di ricerca (BST)
Alberi bilanciati (AVL)
B-tree (gestione memoria secondaria)
Grafi
AN
Tipo astratto coda
Implementazione di code
Con array
n
n
n
Lista nella quale gli inserimenti avvengono in coda e le
cancellazioni (estrazioni) in testa (disciplina FIFO)
Operazioni sempre presenti
q isEmpty(): verifica se la coda è vuota
q enqueue(el): inserisce l'elemento specificato da el
alla fine della coda
q dequeue(): elimina il primo elemento della coda
q firstEl(): restituisce il primo elemento della coda
senza eliminarlo
Altre operazioni
clear(): elimina tutti gli elementi dalla coda
q
A0
A1
A2
AN-3 AN-2 AN-1
testa
coda
Elemento non usato
enqueue -> coda = coda + 1 (mod N)
dequeue -> testa = testa + 1 (mod N)
Se (coda == testa – 1 mod N) coda piena
Se (coda == testa) coda vuota (un solo elemento
presente)
Con liste concatenate
Strutture dati
Tipi di dato astratti
(strutture dati dinamiche)
q
Strutture dati elementari
n
n
n
q
Liste
Stack (pile)
Code
Alberi
n
n
n
n
q
alberi
Alberi binari
Alberi di ricerca (BST)
Alberi bilanciati (AVL)
B-tree (gestione memoria secondaria)
definizione, algoritmi di visita, alberi
binari
Grafi
3
Tipo di dato astratto albero
n
n
Terminologia
insieme vuoto di nodi oppure costituito da una
radice R e da 0 o più alberi (sottoalberi)
la radice di ogni sottoalbero è collegata a R da un
arco
n
genitore, figlio, fratello
n
nodo
q
q
R
q
foglia se ha zero figli
interno se ha almeno un figlio
es.: radice R con n
sottoalberi
T1
T2
n
n
livello radice = 1
lunghezza (n.ro nodi)
percorso radice-nodo
n
percorso radice-foglia
n
altezza = 3
n
n
Rappresentazione di alberi con liste
collegate
Primo figlio
di R
B
q
q
C
Fratello di A
operazioni più importanti
q
R
q
Elemento
continente, nazione, regione, provincia ecc
(alcuni) organigrammi
file system
domini Internet
Operazioni sugli alberi
n
livello di C = 3
ad es., in Java
classificazioni di specie animali
organizzazione del territorio
q
lunghezza (n.ro nodi) ramo
più lungo
A
alberi genealogici
gerarchie di ereditarietà
q
altezza albero
q
n
n
ramo
q
n
foglia
Esempi di alberi
livello di un nodo
q
nodo interno
Tn
Terminologia
n
radice
concetti intuitivi
q
q
element(v): restituisce l’elemento memorizzato nel
nodo v
root(): restituisce la radice dell’albero
parent(v): restituisce il genitore del nodo v
children(v): restituisce i figli di v
isLeaf(v): restituisce true se v è una foglia
isRoot(v): restituisce true se v è la radice
Riferimento al prossimo fratello
Riferimento al primo figlio
4
Operazioni sugli alberi
n
Algoritmi su alberi
Altre operazioni
q
livello di un nodo
altezza dell’albero
# nodi
# foglie
q
max # di figli di un nodo dell’albero
q
q
q
q
n
q
in profondità (depth-first search, a scandaglio):
DFS
q
in ampiezza (breadth-first search, a ventaglio):
BFS
vengono visitati i rami, uno dopo l’altro
n
isEmpty
n
visita (o attraversamento) di un albero
true se l’albero ha zero nodi
a livelli, partendo dalla radice
n
visite in profondità/preordine
n
in preordine (preorder, o ordine anticipato)
q dato un nodo v
n
n
n
Visite in profondità
visita v
visita i sotto-alberi aventi come radice i figli di v, da sinistra verso
destra
2
1
in ordine simmetrico (inorder)
dato un nodo v con k sotto-alberi
7
q
n
n
n
n
2
visita il primo sotto-albero (radice v.firstChild)
visita v
visita gli altri k -1 sotto-alberi
3
4
in postordine (postorder, o ordine posticipato)
q dato un nodo v
n
n
6
7
inordine
3
2
6
4
5
postordine
n
strutture dati per alberi binari
q
5
5
1
un albero si dice binario se ogni nodo può
avere al più 2 figli
q
4
3
6
n
q
3
7
4
Alberi binari
1
2
6
1
preordine
visita i sotto-alberi aventi come radice i figli di v, da sinistra verso
destra
visita v
visita in ampiezza (usa una coda)
5
la rappresentazione si semplifica
vettori
rappresentazioni collegate
7
BFS
5
uso di vettori
ogni nodo v è memorizzato in posizione p(v)
n
q
q
q
se v è la radice allora p(v)=1 (indice 0 in Java, C, C++)
se v è il figlio sinistro di u allora p(v)=2p(u)
se v è il figlio destro di u allora
p(v)=2p(u)+1
1
2
3
4
6
7
-
1
3
2
6
4
7
n Binary
Tipo di dato astratto che supporta le seguenti
operazioni:
q
q
q
n
albero binario che soddisfa la seguente proprietà
search
insert
delete (remove)
Ø per ogni nodo, tutte le chiavi nel suo sottoalbero sinistro
sono ≤ della chiave v associata al nodo e tutti le chiavi nel
suo sottoalbero destro sono ≥ di v
le liste possono essere usate come dizionari
n
n
q
le tre operazioni hanno costo lineare (sia nel worst case
sia in quello average)
in molti casi un costo lineare è giudicato inaccettabile
q
strutture più efficienti?
n
q
n
n
alberi di ricerca bilanciati
tavole hash
49
17
49
82
57
20
22
88
ok
17
94
91
82
47
20
utilizzabile quando le chiavi appartengono a un universo
totalmente ordinato
Una visita simmetrica (inorder) dell’albero da’ le chiavi
dell’albero in modo non descrescente
ipotesi semplificativa di lavoro: chiavi strettamente minori
nei sottoalberi sinistri e strettamente maggiori nei sotto
alberi destri
Costi delle operazioni nei BST: ricerca di un
elemento
albero binario di ricerca
22
Search Tree
Albero binario di ricerca
Dizionari
n
Alberi binari di ricerca (BST)
88
errato!
94
search(tree T, int x) {
v = root(T )
while (v != null) {
if (x == key(v)) return v;
else if (x < key(v)) v = left child (v);
else v = right child (v);
}
return null;
}
91
ricorda la ricerca binaria!
6
costo della ricerca in un BST
BST di n nodi
caso peggiore
49
n
O(n)
q
n
n
caso migliore
Ø
costo dell'inserimento in un BST
q
q
56
dipende dalla distribuzione
54 67
O(1) (poco interessante)
q
n
n
21 52
caso medio
q
Costi delle operazioni nei BST
q
nel caso di distribuzione uniforme delle chiavi il 77
valore atteso dell'altezza dell'albero è O(log n) 75 83
Ø
istanze problematiche: alberi molto profondi e
sbilanciati...
ogni inserimento introduce una nuova foglia
il costo è (proporzionale a) la lunghezza del ramo
radice-foglia
nel caso peggiore O(n )
istanze problematiche nei BST : alberi molto
profondi e sbilanciati...
Introduzione al bilanciamento
Alberi bilanciati
n
nozione intuitiva di bilanciamento
q
q
n
nil
costo delle varie operazioni su BST è O(h),
dove h = altezza dell’albero
npuò essere O(n) worst case!!!
nse l’albero fosse bilanciato…
nma poi dobbiamo mantenerlo tale quando
inseriamo o cancelliamo elementi!
Bilanciamento perfetto
34
n
21
16
6
63
30
43
18 28 32 37 52
72
tutti i rami di un albero hanno
approssimativamente la stessa lunghezza
ciascun nodo interno ha “molti” figli
caso ideale per un albero k-ario
q
q
ciascun nodo ha 0 o k figli
la lunghezza di due rami qualsiasi differisce di al
più una unità
bilanciamento perfetto
un albero binario
perfettamente bilanciato di
n nodi ha altezza
n
lg2 n  + 1
se ogni nodo ha 0 o 2 figli
le foglie sono circa il 50%
dei nodi (interni +foglie)
Il caso binario e’ facilmente generalizzabile ad alberi
di parità k
q
n
n
nf = (k − 1)ni + 1
⇒
nf =
(k − 1)n + 1
k
costo di ricerca/inserimento/eliminazione O(log n)
ripetuti inserimenti/eliminazioni possono distruggere
il bilanciamento
q
degrado delle prestazioni
7
bilanciamento in altezza
Fattore di bilanciamento
un albero è bilanciato in altezza se le altezze
dei sottoalberi sinistro e destro di ogni nodo
differiscono di al più un’unità
gli alberi bilanciati in altezza sono detti alberi
AVL
n
n
q
da Adel’son-Vel’skii & Landis, primi proponenti
n
Alberi di fibonacci
n
q
alberi AVL col minimo numero di nodi (fissata
l’altezza)
34
21
16
3
63
30
43
72
18 28 32 37 52
29
un albero AVL è quindi un albero binario di
ricerca in cui ad ogni nodo v viene associato
un valore detto fattore di bilanciamento che
corrisponde alla differenza tra la profondita’
del sottoalbero sinistro e quello del
sottoalbero destro di v
Il fattore di bilanciamento puo’ assumere solo
I valori -1,0, 1
Bilanciamento
fattore di bilanciamento
6
n
fattore di bilanciamento
(FDB):
altezza sottoalbero dx –
altezza sottoalbero sx
78
57
n
+1
-1
Mantenere la proprieta’ di bilanciamento
durante inseriementi e cancellazioni
garantisce che l’operazione di ricerca abbia
sempre costo logaritmico e quindi sia molto
efficiente
0
in un albero bilanciato in altezza
|FDB| ≤ 1, per ogni nodo
inserimento in AVL
Rotazioni
n
1.
inserire nuovo nodo come in un BST
2.
ricalcolare i fattori di bilanciamento che sono
mutati in seguito all’inserimento
il nuovo nodo diviene una foglia
L’idea alla base delle rotazioni e’ quella di
portare l’elemento centrale alla radice
dell’albero e di far discendere l’elemento che
causa lo sbilanciamento
solo nel ramo interessato all’inserimento (gli altri fattori
non possono mutare), dal basso verso l’alto
3.
se nel ramo appare un fattore di bilanciamento
pari a ±2 occorre ribilanciare
tramite “rotazioni”
8
rotazione
rotazioni negli AVL
verso sinistra o verso destra
casi possibili
verso destra
q
a
b
q
T1
T3
T1
q
a
b
T2
T2
T3
q
verso sinistra
DD: inserimento nel sottoalbero destro di un figlio
destro (del nodo che si sbilancia)
SD: inserimento nel sottoalbero sinistro di un figlio
destro (del nodo che si sbilancia)
DS: inserimento nel sottoalbero destro di un figlio
sinistro (del nodo che si sbilancia)
SS: inserimento nel sottoalbero sinistro di un figlio
sinistro (del nodo che si sbilancia)
la proprietà di ricerca è mantenuta
rotazione semplice (caso DD)
Costo delle operazioni in AVL
n
n
Si dimostra che le rotazioni che si devono
eseguire in seguito ad inseriemnti e/o
cancellazioni non alterano il costo di queste
operazioni che e’ sempre uguale ad O(logn)
come per la ricerca di un elemento.
gli antenati di P non sono interessati
all’inserimento perché in seguito alla rotazione
recuperano il loro fattore di bilanciamento
precedente
Coda con priorità
Heap e code di priorita’
n
n
Una coda con priorità è una struttura dati
dinamica che permette di gestire una
collezione di dati con chiave numerica.
Una coda con priorità offre le operazioni di
inserimento: di un elemento nell’insieme
massimo: restituisce l’elemento con chiave più
grande
q cancellazione-massimo: restituisce l’elemento
con chiave più grande e lo rimuove dalla
collezione
q
q
9
Applicazioni della Coda con Priorità
n
n
Le Code con priorità sono strutture dati molto
comuni in informatica.
Es:
q
n
Gestione di processi: ad ogni processo viene associata
una priorità. Una coda con priorità permette di conoscere
in ogni istante il processo con priorità maggiore. In
qualsiasi momento i processi possono essere eliminati
dalla coda o nuovi processi con priorità arbitraria possono
essere inseriti nella coda.
n
heap = catasta
condizione di heap
albero binario perfettamente bilanciato
ogni nodo contiene una chiave maggiore o eguale di
quelle presenti negli eventuali figli
1.
2.
n
non memorizza un ordinamento totale
le visite in ampiezza e in pre- in- post-ordine non
forniscono un ordinamento delle chiavi
q
rappresentazione tramite array
Si implementa l’albero tramite un vettore
q
q
q
q
q
q
q
Uno heap A ha un attributo heap-size[A] che specifica il
numero di elementi contenuto nello heap
nessun elemento in A[1,length[A]] dopo heap-size[A] è un
elemento valido dello heap
La radice dell’albero è A[1]
L’indice del padre di un nodo di posizione i è i/2
L’indice del figlio sinistro di un nodo i è 2 i
L’indice del figlio destro di un nodo i è 2 i +1
Implemenatzione particolarmente efficiente
n
n
n
Per implementare una coda con priorità utilizzeremo
una struttura dati chiamata heap
Heap
n
heap
n
ogni nodo v è memorizzato in posizione
p(v)
q
q
q
se v è la radice allora p(v)=0
se v è il figlio sinistro di u allora p(v)=2p(u)+1
se v è il figlio destro di u allora
p(v)=2p(u)+2
89
67
66
Tempo di ricerca/ordinamenyto in struttura di heap = O(logn)
1
Liste collegate
68
65
43 21
5
66
67
4 64
89
67
68
66
65
66
67
1
43
21
5
4
64
0
1
2
3
4
5
6
7
8
9
10
11
12
maggio 2002
Coda con priorità con heap
n
Risulta semplice implementare le varie operazioni di
una coda con priorità utilizzando uno heap
q
q
q
Extract Max: basta restituire la radice dello heap
Heap Extract Max: dopo la restituzione dell’elemento
massimo, posiziona l’ultimo elemento dello heap nella
radice ed ripristina la proprietà di ordinamento
parziale
Heap Insert: la procedura inserisce il nuovo elemento
come elemento successivo all’ultimo e lo fa salire fino
alla posizione giusta facendo “scendere” tutti padri
B-alberi
dizionari in memoria secondaria
10
B-Alberi
n
n
n
B-Alberi
I B-Alberi sono una generalizzazione degli
alberi binari di ricerca
la principale differenza è che nei B-Alberi
ogni nodo dell’albero può contenere n>2
chiavi
i B-Alberi sono utilizzati per garantire
l’efficienza delle operazioni su insiemi
dinamici (ricerca, inserzione e cancellazione)
di dati memorizzati su supporti secondari
(dischi)
In ogni istante è possibile mantenere in memoria
primaria solo un numero limitato di pagine della
memoria secondaria
le operazioni eseguite sui B-Alberi garantiscono di
poter essere eseguite conservando solo un numero
costante di pagine in memoria principale (tante più
pagine tanto più efficienti saranno le varie
operazioni)
in genere un nodo di un B-Albero e’ tanto grande
quanto una pagina di memoria secondaria
n
n
n
Esempio n=3
Visualizzazione
127
14
M
DH
BC
FG
128 145
QTX
JKL
NP
RS
VW
YZ
n
n
Dunque, K ´1 < K ´ 2 < … < K ´ n-2 < K ´n- 1
n
n
K1
P1
...
Ki
Pi Ki+1
222
245 320
521
353
354
690
487
Notare che le foglie sono ordinate per chiave, da sinistra
a destra
n
Per inserire la chiave v, si cerca la foglia dove v
dovrebbe trovarsi: se c’e’ spazio, si inserisce
Se no, si spezza la foglia in due, e si modifica il padre
per prevedere i puntatori alle due foglie
n
19
X
12
. . . Kn-1 Pn
--
14 17
15
19
X
K´1 P´1 . . .
352
Inserzione
Ogni nodo e' un sequence di coppie [puntatore, chiave]
K1 < K 2 < … < Kn-2 < Kn- 1
P1 punta a un nodo contenente chiavi < K1
Pi punta a un nodo contenente chiavi in intervallo [Ki-1, Ki)
Pn punta a un nodo contenente chiavi > Kn-1
n
189
221
n
B-albero: esempio
n
83
496
K´i P´i K´i+1 . . . K´n-1 P´n
12 14
15 17
Per inserire la chiave 15
• si spezza la foglia
• nel padre, [0, 19)
diventa [0, 15) e [15, 19)
• se il padre e’ pieno, bisogna
spezzarlo (in modo simile)
• l’albero resta automaticamente
bilanciato
11
Ricerca
n
n
E’ un operazione simile alla ricerca sugli
alberi binari di ricerca
Con la differenza è che non ci sono solo due
vie possibili ad ogni nodo
Grafi
Grafi
Grafi
n
n
Grafo diretto o orientato
q
n
Insieme N di elementi detti nodi e insieme di archi.
Un arco e’ una coppia ordinata (v,e) di nodi.
n
n
Grafo non oreintato
q
Insieme N di elementi detti nodi e insieme di archi.
Un arco e’ una coppia non ordinata (v,e) di nodi.
n
n
Grafi
Rappresentazione di un grafo
n
n
n
n
Se due nodi V1 e V2 sono collegati da un
arco si dice che V1 e’ adiacente a V2
Cammino di un grafo: la sequenza di nodi V1,
V2,.. Vn tali che le coppie (V1,V2) ,(V2,V3),..
(Vn-1, Vn) sono adiacenti
Lunghezza di un cammino: numeor di archi
percorsi (o nuemro di nodi -1)
I grafi sono strutture dati molto diffuse in informatica
Vengono utilizzati per rappresentare reti e
organizzazioni dati complesse e articolate
Per elaborare i grafi in genere è necessario visitarne
in modo ordinato i vertici
Vedremo a questo proposito due modi fondamentali
di visita: per ampiezza e per profondità
Il tempo di esecuzione di un algoritmo su un grafo
G=(V,E) viene dato in funzione del numero di vertici
V e del numero di archi E
Vi sono due modi per rappresentare un grafo:
q
q
n
n
collezione di liste di adiacenza
matrice di adiacenza
si preferisce la rappresentazione tramite liste di
adiacenza quando il grafo è sparso, cioè con E
molto minore di V2
si preferisce la rappresentazione tramite matrice di
adiacenza quando, al contrario, il grafo è denso o
quando occorre alta efficienza nel rilevare se vi è un
arco fra due vertici dati
12
Liste di adiacenza
n
n
n
n
Si rappresenta un grafo G=(V,E) con un
vettore Adj di liste, una lista per ogni vertice
del grafo
per ogni vertice u, Adj[u] contiene tutti i
vertici v adiacenti a u, ovvero quei vertici v
tali per cui esiste un arco (u,v)∈E
in particolare questo insieme di vertici è
memorizzato come una lista
l’ordine dei vertici nella lista è arbitrario
Rappresentazioni
di grafi.
Un grafo (a)
rappresentato
con una lista
di adiacenze
(b-c),
Matrici di adiacenza
n
n
Per la rappresentazione con matrici di
adiacenza si assume che i vertici siano
numerati in sequenza da 1 a V
Si rappresenta un grafo G=(V,E) con una
matrice A=(aij ) di dimensione VxV tale che:
aij=1 se (i,j) ∈ E
aij=0 altrimenti
Rappresentazioni di grafi. Un grafo (a) rappresentato come una matrice
di adiacenze (d)
Visita di un Grafo
Grafi pesati
n
n
n
In alcuni problemi si vuole poter associare
una informazione (chiamata peso) ad ogni
arco
un grafo con archi con peso si dice grafo
pesato
si dice che esiste una funzione peso che
associa ad un arco un valore
Obiettivo: visitare una sola volta tutti i
nodi del grafo.
n
q
Es.: visitare un porzione del grafo del Web
Difficoltà:
n
q
q
Presenza di cicli
Presenza di nodi isolati
w : E→ R
n
ovvero un arco (u,v) ha peso w(u,v)
13
Visita in profondità - DFS
Implementazione della DFS
n
n
n
n
n
La visita procede da tutti gli archi uscenti da un
nodo.
Se tutti i nodi adiacenti sono stati visitati allora si
torna al nodo “predecessore”.
Una volta tornati al nodo di partenza si prosegue
da un nodo qualsiasi non visitato.
I nodi vengono rinumerati secondo l’ordine di
visita.
Visita in profondità - DFS
n
visita_profondità(G)
q
q
n
1. Passo base
se G = Ø f=> esci;
2. Passo di induzione
visita il nodo G se non è stato visitato
per ogni nodo adiacente G->adj
visita_profondità(G->adj);
n
n
n
n
I nodi sono inizialmente marcati con 0, i=0.
Assumi la visita sia arrivata ad un nodo v.
La visita prosegue da un nodo u adiacente a v se
marcato 0.
Se nessun nodo adiacente marcato 0 è disponibile
torna al nodo da cui si è raggiunto v oppure
termina se v è il nodo iniziale.
Ogni volta che un nodo mai visitato è raggiunto,
questo viene marcato con i++
Implementazione della DFS
n
n
n
L’implementazione iterativa usa una pila
per memorizzare gli archi uscenti da un
nodo visitato.
Ad ogni passo si estrae l’arco (v,u) sulla
cima della pila.
La visita prosegue dal nodo adiacente u se
marcato 0.
Osservazione: la visita in profondità è
strettamente legata alla politica di gestione di
uno stack (come tutti gli algoritmiricorsivi);
Esempio di applicazione dell’algoritmo depthFirstSearch
ad un grafo
L’algoritmo depthFirstSearch applicato ad un grafo orientato
14
Visita in profondità (C)
void visita_profondita(struct nodo_grafo*nodo)
{
if (nodo == NULL) return;
if (nodo->flag == 0)
{
printf ("%s\n", nodo->info);
nodo->flag = 1;
adj = nodo->l_adj;
while(adj != NULL)
{
visita_profondita(adj->p_adj);
adj = adj->next;
}
}
return;
}
Visita in ampiezza - BFS
n
n
n
uso di una coda per memorizzare tutti gli
archi incidenti nel nodo visitato
I nodi vengono marcati.
La visita quindi procede dall’arco (v,u) in
testa alla coda.
Visita in ampiezza - BFS
n
visita_ampiezza(G)
per ogni nodo non visitato:
q
q
q
n
si inserisce il nodo in una coda;
si estrae dalla coda un nodo e si visita;
si inseriscono in coda tutti gli elementi adiacenti al
nodo corrente.
Osservazione: la visita in ampiezza è
strettamente legata alla politica di gestione di
una coda;
Un esempio di applicazione dell’algoritmo breadthFirstSearch
ad un grafo
Visita in ampiezza (C)
Applicazione dell’algoritmo breadthFirstSearch ad un grafo orientato
void visita_ampiezza(struct nodo_grafo *nodo)
{
struct punt_adj *adj;
static struct p_coda *first_el;
coda_ins (nodo);
while(first_el != NULL) //finché ci sono elementi nella
coda
{
nodo = coda_extr(); //Estrazione dalla coda di un nodo
printf("nodo->info %c\n", nodo->info); //Visita del nodo
nodo->flag = 1;
adj = nodo->l_adj;
while(adj != NULL) //Inserimento in coda dei nodi
adiacenti
{
if (adj->nodo_adj->flag == 0)
coda_ins (adj->p_adj);
adj = adj->next;
}}}
15