ADT Grafo

Transcript

ADT Grafo
ADT Grafo
L' ADT grafo è un contenitore di elementi memorizzati nelle posizioni
del grafo (vertici e archi)
le informazioni possono essere memorizzate sia sui vertici sia
sugli archi del grafo
Strutture Dati
ADT Grafo
Metodi fondamentali (grafo non orientato)
Metodi iteratore
–
vertices(): restituisce una collezione iterabile su tutti i vertici del grafo
–
edges(): restituisce una collezione iterabile su tutti gli archi del grafo
–
incidentEdges(v): restituisce una collezione iterabile sugli archi incidenti su v
Metodi di accesso
–
–
–
–
–
endVertices(e): restituisce un array dei due vertici estremità di e
opposite(v, e): restituisce il vertice opposto a v sull'arco e
areAdjacent(v, w): vero se e solo se v e w sono adiacenti
replace(v, x): rimpiazza l'elemento memorizzato nel vertice v con x
replace(e, x): rimpiazza l'elemento memorizzato nell'arco e con x
Strutture Dati
ADT Grafo
Metodi fondamentali (grafo non orientato)
Metodi di aggiornamento
–
insertVertex(o): inserisce un vertice che contiene l'elemento o
–
insertEdge(v, w, o): inserisce un arco (v,w) che contiene l'elemento o
–
removeVertex(v): rimuove il vertice v (e i suoi archi incidenti)
–
removeEdge(e): rimuove l'arco e
Strutture Dati
ADT Grafo
Interfaccia Graph
public interface Graph <V,E>{
public int numVertices();
public int numEdges();
public Iterable<Vertex<V>> vertices();
public Iterable<Edge<E>> edges();
public V replace(Vertex<V> p, V o) throws InvalidPositionException;
public E replace(Edge<E> p, E o) throws InvalidPositionException;
public Iterable<Edge<E>> incidentEdges(Vertex<V> v)
throws InvalidPositionException;
public Vertex[] endVertices(Edge<E> e)
throws InvalidPositionException;
...
}
Strutture Dati
ADT Grafo
Interfaccia Graph
public interface Graph <V,E>{
...
public Vertex<V> opposite(Vertex<V> v, Edge<E> e)
throws InvalidPositionException;
public boolean areAdjacent(Vertex<V> u, Vertex<V> v)
throws InvalidPositionException;
public Vertex<V> insertVertex(V o);
public Edge<E> insertEdge(Vertex<V> u, Vertex<V> v, E o)
throws InvalidPositionException;
public V removeVertex(Vertex<V> v) throws InvalidPositionException;
public E removeEdge(Edge<E> e) throws InvalidPositionException;
}
Strutture Dati
ADT Grafo
Decorator pattern
Il decorator pattern è un design pattern che serve ad inserire
informazioni extra (colori) ad un oggetto
Una decorazione consiste di
- una chiave (che identifica il tipo di decorazione)
- un valore associato alla chiave
Strutture Dati
ADT Grafo
Decorator pattern
Esempio:
algoritmi come BFS e DFS richiedono che i nodi e/o gli archi
del grafo vengano colorati per tenere traccia dell'esplorazione
Si può usare un decorator pattern per “decorare” i nodi del grafo:
ad ogni nodo sarà associata una coppia (chiave, valore)
dove la chiave identifica l'attributo esplorato e il valore
(ad essa associato) è un booleano
(esplorato, sì)
Strutture Dati
(esplorato, no)
ADT Grafo
Interfacce Vertex e Edge
public interface DecorablePosition<T> extends Position<T>, Map<Object,Object> {
}
public interface Vertex<V> extends DecorablePosition<V> {
}
public interface Edge<E> extends DecorablePosition<E> {
}
Strutture Dati
ADT Grafo
Uso della decorable position
Esempio:
final Object COLOR = new Object();
final Object WHITE = new Object();
...
chiave
valore
v.put(COLOR, WHITE);
...
if(v.get(COLOR) != WHITE)
...
Strutture Dati
su un oggetto Vertex<V> si possono
usare i metodi della mappa per
gestire le colorazioni
ADT Grafo
Implementazione mediante lista di archi
Ciascun vertice del grafo è rappresentato da un oggetto di tipo vertex,
tutti gli oggetti vertex sono memorizzati in un contenitore V
V
Ciascun arco del grafo è rappresentato da un oggetto di tipo edge,
tutti gli oggetti edge sono memorizzati in un contenitore E
E
Strutture Dati
ADT Grafo
Implementazione mediante lista di archi
Oggetto vertex
o
l'oggetto vertex per un vertice v che memorizza l'elemento o ha:
- un riferimento a o
- un riferimento alla posizione dell'oggetto-vertex nel contenitore V dei
vertici del grafo
Strutture Dati
ADT Grafo
Implementazione mediante lista di archi
Oggetto edge
o
l'oggetto edge per un arco e = (u,v) che memorizza l'elemento o ha:
- un riferimento a o
- un riferimento agli oggetti-vertex per u e v
- un riferimento alla posizione dell'oggetto-edge nel contenitore E degli
archi del grafo
Strutture Dati
ADT Grafo
Implementazione mediante lista di archi
z
u
a
v
c
b
d
V
w
u
a
E
Strutture Dati
v
b
w
z
c
d
ADT Grafo
Implementazione mediante lista di archi
Vantaggi:
- implementazione semplice
- accesso diretto dagli archi ai vertici su cui essi sono incidenti
(endVertices(e) e opposite(v,e) sono semplici da implementare
e richiedono tempo O(1))
Svantaggi:
- l'accesso agli archi che sono incidenti su un dato vertice richiede
un'ispezione esaustiva di tutto il contenitore E. I seguenti metodi
richiedono un tempo proporzionale al numero di archi del grafo:
- incidentEdges(v)
- areAdjacent(v,w)
- removeVertex(v)
Strutture Dati
Grafi
Domanda
Qual è il massimo numero di archi che un grafo G = (V,E) di n = |V|
vertici può avere?
Grafi
Domanda
Qual è il massimo numero di archi che un grafo G = (V,E) di n = |V|
vertici può avere?
grafi orientati
Grafi
Domanda
Qual è il massimo numero di archi che un grafo G = (V,E) di n = |V|
vertici può avere?
grafi orientati
n2
Grafi
Domanda
Qual è il massimo numero di archi che un grafo G = (V,E) di n = |V|
vertici può avere?
grafi orientati
n2
grafi non orientati
Grafi
Domanda
Qual è il massimo numero di archi che un grafo G = (V,E) di n = |V|
vertici può avere?
grafi orientati
n2
grafi non orientati
n
2
( )
Rappresentazione in memoria
Liste di adiacenza e matrice di adiacenza
Esistono due modi per rappresentare un grafo G=(V,E) in
memoria:
liste di adiacenza
matrice di adiacenza
Liste di adiacenza
G =( V,E )
La rappresentazione consiste di un array Adj di |V| liste
(una per ogni vertice)
Per ogni u in V la lista Adj [u] contiene tutti i vertici v adiacenti ad u
in G
Liste di adiacenza
Grafi non orientati
1
G =(V,E) grafo non orientato
2
4
Array Adj di |V| liste:
3
Adj [1], Adj [2], Adj [3], Adj [4], Adj [5]
Adj [1]
1
2
3 /
Adj [2]
2
1
4
Adj [3]
3
1
4 /
Adj [4]
4
2
3
Adj [5]
5
2
4 /
5 /
5 /
5
Liste di adiacenza
Grafi orientati
G =(V,E) grafo orientato
1
2
V= {1,2,3,4,5}
4
Array Adj di |V| liste:
3
Adj [1], Adj [2], Adj [3], Adj [4], Adj [5]
Adj [1]
1
2
Adj [2]
2
4 /
Adj [3]
3
4 /
Adj [4]
4
5 /
Adj [5]
5
2 /
3 /
5
Liste di adiacenza
Spazio di memoria richiesto
1
1
2
2
4
4
3
5
3
5
G =(V,E) grafo orientato
G =(V,E) grafo non orientato
1
2
3 /
2
1
4
3
1
4 /
4
2
3
5
2
4 /
5 /
5 /
1
2
2
4 /
3
4 /
4
5 /
5
2 /
3 /
Liste di adiacenza
Spazio di memoria richiesto
1
2
3 /
2
1
4
3
1
4 /
4
2
3
5
2
4 /
somma delle lunghezze
delle liste =
5 /
5 /
1
2
2
4 /
3
4 /
4
5 /
5
2 /
somma delle lunghezze
delle liste =
3 /
Liste di adiacenza
Spazio di memoria richiesto
1
2
3 /
2
1
4
3
1
4 /
4
2
3
5
2
4 /
somma delle lunghezze
delle liste =
5 /
5 /
1
2
2
4 /
3
4 /
4
5 /
5
2 /
somma delle lunghezze
delle liste = |E|
3 /
Liste di adiacenza
Spazio di memoria richiesto
1
2
3 /
2
1
4
3
1
4 /
4
2
3
5
2
4 /
somma delle lunghezze
delle liste = 2|E|
5 /
5 /
1
2
2
4 /
3
4 /
4
5 /
5
2 /
somma delle lunghezze
delle liste = |E|
3 /
Liste di adiacenza
Spazio di memoria richiesto
1
2
3 /
2
1
4
3
1
4 /
4
2
3
5
2
4 /
somma delle lunghezze
delle liste = 2|E|
5 /
5 /
1
2
2
4 /
3
4 /
4
5 /
5
2 /
somma delle lunghezze
delle liste = |E|
Spazio di memoria richiesto in entrambi i casi:
3 /
Liste di adiacenza
Spazio di memoria richiesto
1
2
3 /
2
1
4
3
1
4 /
4
2
3
5
2
4 /
somma delle lunghezze
delle liste = 2|E|
5 /
5 /
1
2
2
4 /
3
4 /
4
5 /
5
2 /
somma delle lunghezze
delle liste = |E|
Spazio di memoria richiesto in entrambi i casi:
Θ(max{|V|,|E|}) = Θ(|V|+|E|)
3 /
Liste di adiacenza
Grafi pesati
Un grafo pesato G è una coppia (V,E)
con una funzione peso w: E
R
Il peso w(u,v) di ogni arco (u,v) in E viene memorizzato nella lista di u
insieme a v in un nuovo campo.
6
1
2
5
10
23
3
4
19
3
5
1
2 6
2
4 5 /
3
4 23 /
4
5 19 /
5
2 3 /
3 10 /
Liste di adiacenza
Vantaggi e svantaggi
Buone notizie
Spazio di memoria richiesto: Θ(|V|+|E|)
Cattive notizie
Non esiste un modo veloce per determinare se un dato arco
(u,v) è presente nel grafo.
Unico modo: scandire la lista di adiacenza di u alla ricerca di v
ADT Grafo
Implementazione con liste di adiacenza
Come nella implementazione mediante lista di archi:
Ciascun vertice del grafo è rappresentato da un oggetto di tipo vertex,
tutti gli oggetti vertex sono memorizzati in un contenitore V
Ciascun arco del grafo è rappresentato da un oggetto di tipo edge,
tutti gli oggetti edge sono memorizzati in un contenitore E
Strutture Dati
ADT Grafo
Implementazione con liste di adiacenza
Oggetto vertex
o
l'oggetto vertex per un vertice v che memorizza l'elemento o ha:
- un riferimento a o
- un riferimento alla posizione dell'oggetto-vertex nel contenitore V dei
vertici del grafo
- un riferimento a un contenitore I(v) (contenitore di incidenza di v)
i cui elementi hanno i riferimenti agli archi incidenti su v
Strutture Dati
ADT Grafo
Implementazione con liste di adiacenza
Oggetto edge
o
l'oggetto edge per un arco e = (u,v) che memorizza l'elemento o ha:
- un riferimento a o
- un riferimento agli oggetti-vertex per u e v
- un riferimento alla posizione dell'oggetto-edge nel contenitore E degli
archi del grafo
- un riferimento alle posizioni associate all'arco e nei contenitori di
incidenza I(u) e I(v)
Strutture Dati
ADT Grafo
Implementazione con liste di adiacenza
a
u
v
b
V
w
u
v
I(u)
I(v)
a
E
Strutture Dati
w
I(w)
b