Grafos y Arboles
Transcript of Grafos y Arboles
Estructuras de Datos y AlgoritmosFacultad de Informatica
Universidad Politecnica de Valencia
Curso 2008/2009
Tema 4:
Grafos y arboles
FI– UPV: Curso 2008/2009
EDA-4
TEMA 4. Grafos y arboles
Objetivos
• Definiciones, representacion y recorrido de arboles y grafos.
Contenidos
1 Grafos: Definiciones basicas2 Representacion de grafos3 Arboles: Definiciones basicas4 Arboles binarios5 Representacion de arboles6 Recorridos de arboles binarios7 Recorrido de grafos8 Orden topologico en grafos acıclicos
Bibliografıa
• Introduction to Algorithms, de Cormen, Leiserson y Rivest (sec. 5.4, 5.5, 11.4 y 23.1)• Estructuras de datos y algoritmos, de Aho, Hopcroft y Ullman (capıtulos 3, 6 y 7)
FI– UPV: Curso 2008/2009 Pagina 4.1
EDA-4
1. GRAFOS: DEFINICIONES BASICAS
Grafo dirigido: es un par G = (V,A) donde V es un conjunto finito de elementosllamados vertices y A ⊆ V × V es un conjunto de “pares ordenados” de vertices llamadosaristas.
Si (u, v) es una arista de G, se dice que el vertice v es adyacente a u.
0 1 2
53 4
FI– UPV: Curso 2008/2009 Pagina 4.2
EDA-4
1. GRAFOS: DEFINICIONES BASICAS
Grafo no dirigido: es un par G = (V,A) donde V es un conjunto finito de vertices yA ⊆ {{u, v} | u, v ∈ V ∧ v 6= u} es un conjunto de “pares no ordenados” de vertices.
Si a = {u, v} es una arista no dirigida, se dice que a une a u y v y que a incide en u y v.
Si {u, v} es una arista de G, se dice que el vertice v es adyacente a u. La relacion essimetrica.
0 1
4 3
2
FI– UPV: Curso 2008/2009 Pagina 4.3
EDA-4
1. GRAFOS: DEFINICIONES BASICAS
Grado: para todo vertice v,
• grado de entrada es el numero de aristas que inciden en v;• grado de salida es el numero de aristas que emergen de v;• grado es la suma de los grados de entrada y salida de v.
El grado de un grafo es el maximo grado de sus vertices.
0 1 2
53 4
Ejem.: El grado de entrada del vertice 1 es 2; el grado de salida es 1; el grado del vertice es 3. El grado del
grafo es 3.
FI– UPV: Curso 2008/2009 Pagina 4.4
EDA-4
1. GRAFOS: DEFINICIONES BASICAS
Camino desde un vertice u ∈ V a un vertice v ∈ V : es una secuencia 〈v0, v1, . . . , vk〉 devertices de G = (V,A) tal que v0 = u, vk = v, (vi, vi+1) ∈ A, 0 ≤ i < k.La longitud de un camino 〈v0, v1, . . . , vk〉 es el numero de aristas que lo forman.Camino simple: es un camino 〈v0, v1, . . . , vk〉 en el que todos sus vertices son distintos,excepto quizas el primero y el ultimo.Ciclo: es un camino simple 〈v0, v1, . . . , vk〉 tal que v0 = vk y el camino contiene al menosuna arista.Un bucle es un ciclo de longitud 1.
0 1 2
53 4
Ejem.: El camino 〈0, 3, 1, 4〉 es simple y tiene longitud 3. El camino 〈0, 1, 4, 3, 1〉 no es simple.
Ejem.: El camino 〈1, 4, 3, 1〉 es un ciclo de longitud 3. El ciclo 〈5, 5〉 es un bucle.
Grafo acıclico: es un grafo sin ciclos.
FI– UPV: Curso 2008/2009 Pagina 4.5
EDA-4
1. GRAFOS: DEFINICIONES BASICAS
Subgrafo: G′ = (V ′, A′) es un subgrafo de G = (V,A) si V ′ ⊆ V ∧A′ ⊆ A.Subgrafo inducido: Dado V ′ ⊆ V , el subgrafo de G inducido por V ′ es G′ = (V ′, A′)tal que A′ = {(u, v) ∈ A | u, v ∈ V ′}.
0 1 2
53 4
0 1
3 4
0 1
3 4
Subgrafo Subgrafo inducido por V ′ = {0, 1, 3, 4}
FI– UPV: Curso 2008/2009 Pagina 4.6
EDA-4
1. GRAFOS: DEFINICIONES BASICAS
Vertice alcanzable desde un vertice u: es cualquier vertice v para el que existe uncamino de u a v.Las componentes conexas en un grafo no dirigido son las clases de equivalencia devertices segun la relacion “ser alcanzable”.
• Un grafo no dirigido es conexo si ∀u, v ∈ V , v es alcanzable desde u. Es decir, si tieneuna unica componente conexa.
Las componentes fuertemente conexas en un grafo dirigido son las clases deequivalencia de vertices segun la relacion “ser mutuamente alcanzable”.
• Un grafo dirigido es fuertemente conexo si ∀u, v ∈ V , v es alcanzable desde u.
0 1
4 3
2
0 1 2
53 4
FI– UPV: Curso 2008/2009 Pagina 4.7
EDA-4
1. GRAFOS: DEFINICIONES BASICAS
Grafo completo: es un grafo G = (V,A) en el que ∀u, v ∈ V , u 6= v, (u, v) ∈ A.Grafo etiquetado: es un grafo G = (V,A) acompanado de una funcion f : A → E,donde E es un conjunto cuyas componentes se denominan etiquetas.Grafo ponderado: es un grafo etiquetado con numeros reales (E ≡ R).Un grafo se considera denso si |A| ≈ |V |2.Un grafo se considera disperso si |A| <<< |V |2.
FI– UPV: Curso 2008/2009 Pagina 4.8
EDA-4
2. REPRESENTACION DE GRAFOS: Matriz de adyacencias
Un grafo G = (V,A) se representa como G: matriz[V, V ] de booleanos. La componenteG[u, v] es 1 si (u, v) ∈ A; sino G[u, v] = 0.
Memoria: O(|V |2) → grafos densos |A| ≈ |V |2.Tiempo de acceso: O(1). Lista adyacentes: O(|V |). Lista incidentes: O(|V |).
0 1 2
53 4
0
0
0
0
0
0
1 0 1 0 0
0
0
1
0
0
0
0
0
0
0
0
0
0
1
0
1
1
0
0
0
0
1
0
1
0
0
1
2
3
4
5
0 1
4 3
2
1 0 0 1
0
1
1
1
1
0
1
0
1
1
0
1
1
0
1
0
0
1
2
3
4
0
1
0
0
1
FI– UPV: Curso 2008/2009 Pagina 4.9
EDA-4
1 // Representacion de Grafos: Matriz de adyacencia2 #include <vector>3 #include <iostream>4 using namespace std;5 class grafoDirigidoBitMat {6 int numVert;7 vector<bool> vec;8 int indice(int u, int v) const { return u*numVert+v; }9 public:
10 grafoDirigidoBitMat(int nvert) : numVert(nvert),vec(nvert*nvert) {}11 void insertar_arista(int u, int v) { vec[indice(u,v)] = true; }12 bool existe_arista(int u, int v) const { return vec[indice(u,v)]; }13 void imprime(ostream &s) const;14 };15 void grafoDirigidoBitMat::imprime(ostream &s) const {16 for (int u=0; u < numVert; ++u) {17 for (int v=0; v < numVert; ++v)18 s << ((vec[indice(u,v)]) ? ’1’ : ’0’) << ’ ’;19 s << endl;20 }21 }
FI– UPV: Curso 2008/2009 Pagina 4.10
EDA-4
22 ostream& operator << (ostream& s, const grafoDirigidoBitMat &grafo) {23 grafo.imprime(s); return s;24 }25 int main(int argc, char *argv[]) {26 if (argc != 2) {27 cerr << "Uso: " << argv[0] << " maxNodos\n"; exit(0);28 }29 int numVert = atoi(argv[1]);30 grafoDirigidoBitMat gdmat(numVert);31 int u,v;32 while (cin >> u >> v) { // lectura de aristas33 if (0<=u && u<numVert && 0<=v && v<numVert)34 gdmat.insertar_arista(u, v);35 }36 // volcamos la matriz por salida estandar37 cout << "\nMatriz de adyacencia\n" << gdmat << endl;38 return 0;39 }
FI– UPV: Curso 2008/2009 Pagina 4.11
EDA-4
2. REPRESENTACION DE GRAFOS: Listas de adyacencia
Un grafo G = (V,A) se representa como un vector de listas de vertices indexado por vertices;es decir, G: vector[V ] de V . Cada componente G[v] es una lista de los vertices emergentesy/o incidentes de/a v ∈ V .
Memoria: O(|V |+ |A|) → grafos dispersos |A| <<< |V |2.Tiempo de acceso: O(grado(G)). Lista adyacentes: O(grado(G)). (Lista incidentes:O(grado(G)) con listas de incidencia.)
0 1 2
53 4
0
1
2
3
4
5
4 5 NIL
1 NIL
3 NIL
5 NIL
4 NIL
1 3 NIL
0 1
4 3
2
0
1
2
3
4
3 1 NIL
0
1 4 NIL
4 3 2 NIL
3 0 1 NIL
4 2 1 NIL
FI– UPV: Curso 2008/2009 Pagina 4.12
EDA-4
1 // Representacion de Grafos: Listas de adyacencia2 #include <iostream>3 using namespace std;4 class grafoListaAd {5 struct arista {6 int vertice_destino;7 arista *sig;8 arista (int v, arista *s) { vertice_destino=v; sig=s; }9 };
10 int numVert;11 arista **vec;12 public:13 grafoListaAd(int numVert);14 bool existe_arista(int u, int v) const;15 void insertar_arista(int u, int v, bool nueva=false);16 void imprime(ostream &s) const;17 };18 grafoListaAd::grafoListaAd(int numVert) {19 this->numVert = numVert;20 vec = new arista*[numVert];21 for (int i=0; i < numVert; i++) vec[i] = 0;22 }
FI– UPV: Curso 2008/2009 Pagina 4.13
EDA-4
23 bool grafoListaAd::existe_arista(int u, int v) const {24 for (const arista *r = vec[u]; r != 0; r = r->sig)25 if (r->vertice_destino == v) return true;26 return false;27 }28 void grafoListaAd::insertar_arista(int u, int v, bool nueva) {29 if (nueva || !existe_arista(u,v))30 vec[u] = new arista(v,vec[u]);31 }32 void grafoListaAd::imprime(ostream &s) const {33 for (int i=0; i < numVert; i++) {34 s << i << ":";35 for (const arista *r = vec[i]; r != 0; r = r->sig) {36 if (r != vec[i]) s << ",";37 s << r->vertice_destino;38 }39 s << endl;40 }41 }42 ostream& operator << (ostream& s, grafoListaAd &grafo) {43 grafo.imprime(s); return s;44 }
FI– UPV: Curso 2008/2009 Pagina 4.14
EDA-4
45 int main(int argc, char *argv[]) {46 if (argc != 2) {47 cerr << "Uso: " << argv[0] << " maxNodos\n"; exit(0);48 }49 int numVert = atoi(argv[1]);50 grafoListaAd list_ad(numVert);51 int u,v;52 while (cin >> u >> v) { // lectura de aristas53 if (0 <= u && u < numVert && 0 <= v && v < numVert)54 list_ad.insertar_arista(u, v);55 }56 // volcado por salida estandar57 cout << "\nListas de adyacencia\n" << list_ad << endl;58 return 0;59 }
FI– UPV: Curso 2008/2009 Pagina 4.15
EDA-4
Resumen: Representacion de grafos
EspacioMatriz de adyacencia Θ(|V |2)Listas de adyacencia Θ(|V |+ |A|)
Construccion del grafo (u, v) ∈ AMatriz de adyacencia Θ(|V |2) Θ(1)Listas de adyacencia Θ(|V |+ |A|) Θ(grado salida(u))
Recorrido sucesores Recorrido predecesoresMatriz de adyacencia Θ(|V |) Θ(|V |)Listas de adyacencia Θ(grado salida(u)) Θ(|V |+ |A|)Listas de incidencia Θ(|V |+ |A|) Θ(grado entrada(u))
FI– UPV: Curso 2008/2009 Pagina 4.16
EDA-4
Ejercicio: Grafo traspuesto
El grafo traspuesto de un grafo dirigido G = (V,A) es un grafoGt = (V,At) donde (u, v) ∈ At si y solo si (v, u) ∈ A. Escribe dosalgoritmos que permitan construir el grafo traspuesto Gt a partirde G:
En el primer algoritmo los grafos se representaran mediantematrices de adyacencia.En el segundo algoritmo los grafos se representaran mediantelistas de adyacencia.
Calcula el coste computacional de los dos algoritmos.
FI– UPV: Curso 2008/2009 Pagina 4.17
EDA-4
Ejercicio: Grafo traspuesto
Se puede modificar el propio grafo:
1 void grafoDirigidoBitMat::trasponer () { // in place2 for (int u=0; u < vertices; ++u)3 for (int v=0; v < u; ++v) {4 bool aux = vec[indice(u,v)];5 vec[indice(u,v)] = vec[indice(v,u)];6 vec[indice(v,u)] = aux;7 }8 }
Coste: Recorrer la matriz Θ(|V |2)
FI– UPV: Curso 2008/2009 Pagina 4.18
EDA-4
Ejercicio: Grafo traspuesto
O bien devolver otra instancia de la clase:
1 grafoListaAd* grafoListaAd::trasponer() const { // devuelve OTRO grafo2 grafoListaAd* resul = new grafoListaAd(numVert);3 for (int u=0; u < numVert; ++u)4 for (const arista *r = vector[u]; r != 0; r = r->sig) {5 int v = r->vertice_destino;6 // le decimos true para no subir el coste innecesariamente:7 resul->insertar_arista(v,u,true);8 }9 return resul;
10 }
Coste: Recorrer la matriz Θ(|V |+ |A|)
FI– UPV: Curso 2008/2009 Pagina 4.19
EDA-4
Ejercicio: Cuadrado de un grafo
El cuadrado de un grafo dirigido G = (V,A) se define comoG2 = (V,A′) tal que (u, w) ∈ A′ si y solo si para algun v ∈ V secumple que (u, v) ∈ A y (v, w) ∈ A en el grafo G.
Escribe dos algoritmos para calcular G2 a partir de G, suponien-do que este ultimo esta representado como una matriz deadyacencia y como lista de adyacencia.
Calcula el coste temporal de los algoritmos resultantes, justif-icandolo adecuadamente.
FI– UPV: Curso 2008/2009 Pagina 4.20
EDA-4
Ejercicio: Cuadrado de un grafo
Solucion con matriz de adyacencia:
1 grafoDirigidoBitMat* grafoDirigidoBitMat::cuadrado() const {2 // devuelve otro grafo3 grafoDirigidoBitMat *resul = new grafoDirigidoBitMat(numVert);4 for (int u=0; u<numVert; ++u)5 for (int v=0; v<numVert; ++v) {6 bool camino=false;7 for (int w=0; w<numVert && !camino; ++w)8 camino = camino || (vec[indice(u,w)] && vec[indice(w,v)]);9 resul->vec[indice(u,v)] = camino;
10 }11 return resul;12 }
Coste:∑|V |
u=1
∑|V |v=1
∑|V |w=1 1 ∈ O(|V |3)
FI– UPV: Curso 2008/2009 Pagina 4.21
EDA-4
Ejercicio: Cuadrado de un grafo
Solucion con listas de adyacencia:
1 grafoListaAd *grafoListaAd::cuadrado() const {2 grafoListaAd *resul = new grafoListaAd(vertices);3 for (int u=0; u<vertices; ++u)4 for (const arista* r=vec[u]; r!=0; r=r->sig)5 for (const arista* s=vec[r->vertice_destino]; s!=0; s=s->sig)6 resul->insertar_arista(u, s->vertice_destino);7 return resul;8 }
FI– UPV: Curso 2008/2009 Pagina 4.22
EDA-4
3. ARBOLES: DEFINICIONES BASICAS
Bosque: es un grafo no dirigido acıclico.
Arbol libre: es un grafo no dirigido acıclico conexo.
Arbol de recubrimiento de un grafo no dirigido G = (V,A): es un arbol libreT = (V ′, A′) tal que V ′ = V y A′ ⊆ A.
Grafo Bosque Arbol
FI– UPV: Curso 2008/2009 Pagina 4.23
EDA-4
3. ARBOLES: DEFINICIONES BASICAS
Teorema (Propiedades de los arboles libres):
Sea G = (V,A) un grafo no dirigido. Los siquientes predicados son equivalentes:
1. G es un arbol libre.2. Cualquier par de vertices esta conectados por un unico camino.3. G es conexo, pero si se elimina cualquier arista de A, el grafo resultante
no es conexo.4. G es conexo y tiene |V | − 1 aristas.5. G es acıclico, y tiene |V | − 1 aristas.6. G es acıclico, pero si se anade una arista, se crea un ciclo.
Arbol
FI– UPV: Curso 2008/2009 Pagina 4.24
EDA-4
3. ARBOLES: DEFINICIONES BASICAS
Arbol enraizado
Un arbol enraizado es un arbol libre con un vertice (o nodo) distinguido denominado raız.
7
3
8 12
10 4
11 2
56 1
9
raíz
Si existe un camino de un nodo x a un nodo y en un arbol T , se dice que x es antecesorde y, y que y es sucesor de x.Si (x, y) es el ultimo arco en el camino desde la raız r del arbol T hasta el nodo y,entonces x es el padre de y, e y es el hijo de x. La raız es el unico nodo en T que notiene padre. Si dos nodos tienen el mismo padre son hermanos.
FI– UPV: Curso 2008/2009 Pagina 4.25
EDA-4
3. ARBOLES: DEFINICIONES BASICAS
Arbol enraizado
Un nodo sin hijos lo denominaremos hoja. El resto son nodos internos.El grado de un nodo es el numero de hijos que tiene.Se llama profundidad de un nodo a la longitud del camino desde la raız a ese nodo.La altura de un arbol es la profundidad del nodo mas profundo.
7
3
8 12
10 4
11 2
56 1
9
profundidad 0
profundidad 1
profundidad 2
profundidad 3
profundidad 4
altura=4
FI– UPV: Curso 2008/2009 Pagina 4.26
EDA-4
4. ARBOLES BINARIOS
Un arbol binario es un arbol en el que el maximo numero de hijos de cadanodo es 2 (hijo izquierdo e hijo derecho).
3
2
4 1
7
5
6
profundidad 0
profundidad 1
profundidad 2
profundidad 3
altura=3
Un arbol binario se dice que es completo (o lleno) si todas las hojas tienenla misma profundidad y todos los nodos internos tienen grado 2.Un arbol binario es casi-completo si el arbol es completo, a excepcion quizasen el nivel de las hojas, en el cual todas las hojas estan tan a la izquierdacomo sea posible.
FI– UPV: Curso 2008/2009 Pagina 4.27
EDA-4
Propiedades de los arboles binarios completos
0
1
2
3
h=3
1=2_0
2=2_1
4=2_2
8=2_3
profundidad num. nodos
Arbol binario completo de altura h = 3, con 8 hojas y 7 nodos internos
Numero de nodos: La raız tiene 2 hijos de profundidad 1, cada uno de los cuales tienen 2hijos de profundidad 2, etc. → Nodos de profundidad i = 2i.
hojas: 2h y nodos internos: 20 + 21 + · · ·+ 2h−1 =∑h−1
i=0 2i = 2h − 1
nodos total: n =∑h
i=0 2i = 2h+1 − 1
. . . y la altura
n = 2h+1 − 1 → h = blog2 nc
FI– UPV: Curso 2008/2009 Pagina 4.28
EDA-4
Propiedades de los arboles binarios
El maximo numero de nodos de profundidad i es 2i.
El maximo numero de nodos en un arbol binario de altura h es2h+1− 1. El maximo numero de nodos internos es 2h− 1. El maximonumero de hojas es 2h.
La altura mınima de un arbol binario con n nodos es blog2 nc.Para cualquier arbol binario no vacıo, si n0 es el numero de hojas yn2 es el numero de nodos de grado 2, entonces n0 = n2 + 1.
Ejercicio. Arboles k-arios. Un arbol k-ario es un arbol en el que elmaximo numero de hijos de cada nodo es k (ası, un arbol binario es unarbol k-ario con k = 2). ¿Cuantas hojas tiene un arbol k-ario completode altura h? ¿Y cuantos nodos internos?
FI– UPV: Curso 2008/2009 Pagina 4.29
EDA-4
5. REPRESENTACION DE ARBOLES
Arboles (numero de hijos sin acotar)
• Listas (ordenadas) de hijos.
• Hijo mas a la izquierda-Hermano derecha: variables dinamicaso vectores.
• Con vectores y direccion del padre.
• Otros . . .
Arboles binarios
• Hijo izquierdo e Hijo derecho para cada nodo: variablesdinamicas o vectores.
• Arbol binario (casi-completo): vector (“heaps”).
• Otros . . .
FI– UPV: Curso 2008/2009 Pagina 4.30
EDA-4
5. REPRESENTACION DE ARBOLES
Listas (ordenadas) de hijos
1
3
10
5 6 7 11 12
2 9
4 8
1
2
3
4
5
6
7
10
8
9
10
11
12
NIL
5 6 NIL7
NIL
11 12NIL
NIL
NIL
NIL
NIL
NIL
NIL
2 3 NIL9
4 8 NIL
raíz
FI– UPV: Curso 2008/2009 Pagina 4.31
EDA-4
5. REPRESENTACION DE ARBOLES
Hijo mas a la izquierda-Hermano derecha: variables dinamicas o vectores
B I
D H
A
C
J
E F G K L
2
3
4
....
8
9
10
....
12
13
14
16
17
....
15
K
F
L
E
16
12
7
15
3
17
8
NIL
NIL
13
NIL
14
C
D
A
H
I
G
J
10
9
2B
NIL
NIL
NIL
NIL
NIL
NIL
NIL
NIL
NIL
raíz
clavehizq her_d
A
C
E F G K L
D H
B I
J
raíz
hizq her_dclave
FI– UPV: Curso 2008/2009 Pagina 4.32
EDA-4
5. REPRESENTACION DE ARBOLES
Con vectores y direccion del padre
1
10
5 6 7 11 12
4 8
2 91
10
5 6 7 11 12
4 8
2 9
33
1 2 3 4 5 6 7 8 9 10 11 12
3 3 31 1 94 4 4 10 103
El nodo i es la raız del arbol si T [i] = i. Cada nodo apunta a supadre: T [i] = padre(i).
FI– UPV: Curso 2008/2009 Pagina 4.33
EDA-4
5. REPRESENTACION DE ARBOLES
Arboles binarios: variables dinamicas o vectores(opcionalmente, puntero al padre)
C
B
D A
G
E
F
2
3
4
....
8
9
10
....
12
13
14
16
17
....
15 F
E
15
3
17
A
D
C
G
2B
NIL
12
NIL
raíz 8
NIL NIL
NIL
NIL NIL
NIL
clavehderhizq
C
B
D A E
F
G
hizq hderclave
raíz
FI– UPV: Curso 2008/2009 Pagina 4.34
EDA-4
5. REPRESENTACION DE ARBOLES
Arboles binarios (casi-completos): vector
raiz: T[1]padre[i]=[i/2]hizquierdo[i]=2ihderecho[i]=2i+1
A
B C
G
KH I J L
FED
1
5
8 9 10 11 12
6 7
32
4
1 2 3 4 5 6 7 8 9 10 11 12
A ID H JE F G K L
13 14 ...
CB
hizquierdotalla=12raíz
padre
hderechoFI– UPV: Curso 2008/2009 Pagina 4.35
EDA-4
6. RECORRIDOS DE ARBOLES BINARIOS
A veces puede interesar un recorrido sistematico y eficiente de todos los nodos del arbol.
A
B C
D E F
GH I
J
Recorrido en preorden: A B D E H J I C F G
Recorrido en inorden: D B H J E I A F G C
Recorrido en postorden: D J H I E B G F C A
Recorrido en niveles: A B C D E F H I G J
Coste de todos los algoritmos Θ(n), siendo n el numero de nodos del arbol → despues de lallamada inicial, la funcion se llama recursivamente exactamente 2 veces para cada nodo delarbol: una vez para su hijo izquierdo y otra para su hijo derecho.
FI– UPV: Curso 2008/2009 Pagina 4.36
EDA-4
6. Recorridos de arboles binarios: PREORDEN
La clave de la raız se imprime antes de los valores de sus subarboles
A
B C
D E F
GH I
J
9 void nodo_abb::preorden() {10 cout << valor << endl;11 if (h_izq != 0) h_izq->preorden();12 if (h_der != 0) h_der->preorden();13 }
FI– UPV: Curso 2008/2009 Pagina 4.37
EDA-4
6. Recorridos de arboles binarios: INORDEN
La clave de la raız se imprime entre los valores de su subarbol izquierdo y derecho
A
B C
D E F
GH I
J
14 void nodo_abb::inorden() {15 if (h_izq != 0) h_izq->inorden();16 cout << valor << endl;17 if (h_der != 0) h_der->inorden();18 }
FI– UPV: Curso 2008/2009 Pagina 4.38
EDA-4
6. Recorridos de arboles binarios: POSTORDEN
La clave de la raız se imprime despues de los valores de sus subarboles
A
B C
D E F
GH I
J
19 void nodo_abb::postorden() {20 if (h_izq != 0) h_izq->postorden();21 if (h_der != 0) h_der->postorden();22 cout << valor << endl;23 }
FI– UPV: Curso 2008/2009 Pagina 4.39
EDA-4
6. Recorridos de arboles binarios: NIVELES
En lugar de una pila (recursion) se utiliza una cola.
24 void abb::por_niveles() {25 cola *c = new cola(); // una cola de nodo_abb*26 nodo_abb *n;27 c->insertar(raiz);28 while (c->extraer(n)) {29 if (n != 0) { // se puede poner if (n) {30 cout << n->valor << endl;31 c->insertar(n->h_izq);32 c->insertar(n->h_der);33 }34 }35 delete c;36 }
FI– UPV: Curso 2008/2009 Pagina 4.40
EDA-4
Ejemplo arboles binarios: arbol de expresiones
Utilizacion de la estructura AB para representar expresiones aritmeticas con operadoresbinarios.
raız: operador principal
nodos internos: operadores de subexpresiones
hojas: operandos
(niveles: precedencia relativa de evaluacion)
x
+ -
e
a b
dc/
Recorrido en preorden: × + / a b c − d enotacion prefija o polaca
Recorrido en inorden: (((a/b) + c) × (d−e))notacion infija
Recorrido en postorden: a b / c + d e − ×notacion postfija o polaca inversa
FI– UPV: Curso 2008/2009 Pagina 4.41
EDA-4
7. RECORRIDOS DE GRAFOS
Metodo para recorrer de forma sistematica y eficiente un grafo.
Recorrido en profundidad: generalizacion del recorrido en preorden deun arbol
Recorrido en amplitud: generalizacion del recorrido en niveles de unarbol
En todos los algoritmos de recorrido de grafos supondremos que el grafoesta implementado con listas de adyacencia.
FI– UPV: Curso 2008/2009 Pagina 4.42
EDA-4
Recorrido en profundidad de un grafo
Dado un grafo G = (V,A) y un vertice v ∈ V , la estrategia de recorridoen profundidad (Depth-First Search (DFS)), explora sistematicamentelas aristas de G de manera que primero se visitan los vertices adyacentesa los visitados mas recientemente. De esta forma, se va profundizandoen el grafo; es decir, alejandose progresivamente de v.Este proceso continua hasta que todos los vertices alcanzables desde elvertice de la llamada original han sido descubiertos.Esta estrategia admite una implementacion simple de forma recursiva yproporciona:
Ordenamientos de los vertices.
Clasificacion de las aristas.
Algunas aplicaciones:
Calcular un posible orden topologico y comprobar si el grafo es acıclico.
Encontrar las componentes fuertemente conexas de un grafo.
FI– UPV: Curso 2008/2009 Pagina 4.43
EDA-4
Recorrido en profundidad de un grafo
El algoritmo DFS asocia los siguientes datos a cada vertice v del grafo:
d[v] ⇒ instante en que el vertice v es descubierto
f[v] ⇒ instante en que finaliza la exploracion del vertice v
pr[v] ⇒ el vertice predecesor de v en el arbol generado (arbol deexploracion primero en profundidad, es un subgrafo del grafo original).
El color asociado al vertice, que puede ser de 3 tipos:
• WHITE ⇒ cuando nunca ha sido explorado,
• GRAY ⇒ mientras esta siendo explorado,
• BLACK ⇒ cuando ya ha sido explorado.
Al principio todos los vertices se ponen de color WHITE. Se utiliza unatributo time como contador para marcar los instantes.
FI– UPV: Curso 2008/2009 Pagina 4.44
EDA-4
Recorrido en profundidad de un grafo
1 void grafo::dfs_visit(int u) {// algoritmo recursivo del DFS2 color[u] = GRAY;3 d[u] = ++time;4 for (arista *r = vec[u]; r != 0; r = r->sig) {5 int v = r->vertice_destino;6 if (color[v] == WHITE) { pr[v] = u;7 dfs_visit(v); }8 }9 color[u] = BLACK;
10 f[u] = ++time;11 }12 void grafo::dfs() {13 for (int u=0; u < numVert; ++u) { color[u] = WHITE;14 pr[u] = -1; }15 time = 0;16 for (int u=0; u < numVert; ++u)17 if (color[u] == WHITE) dfs_visit(u);18 }
Coste Θ(|V |+ |A|)
FI– UPV: Curso 2008/2009 Pagina 4.45
EDA-4
Recorrido en profundidad de un grafo: Ejemplo
Grafo:8 verticesaristas:0 10 20 30 41 42 33 13 45 66 75 77 5
FI– UPV: Curso 2008/2009 Pagina 4.46
EDA-4
Recorrido en profundidad de un grafo: Ejemplo
dfs_visit(0)(0,4) is a TREE EDGEdfs_visit(4)(0,3) is a TREE EDGEdfs_visit(3)
(3,4) is a FORWARD/CROSS EDGE(3,1) is a TREE EDGEdfs_visit(1)
(1,4) is a FORWARD/CROSS EDGE(0,2) is a TREE EDGEdfs_visit(2)
(2,3) is a FORWARD/CROSS EDGE(0,1) is a FORWARD/CROSS EDGE
dfs_visit(5)(5,7) is a TREE EDGEdfs_visit(7)
(7,5) is a BACK EDGE(5,6) is a TREE EDGEdfs_visit(6)
(6,7) is a FORWARD/CROSS EDGE
FI– UPV: Curso 2008/2009 Pagina 4.47
EDA-4
Recorrido en profundidad de un grafo: Ejemplo
v d[v] f[v] pr[v]0 1 10 -11 5 6 32 8 9 03 4 7 04 2 3 05 11 16 -16 14 15 57 12 13 5
FI– UPV: Curso 2008/2009 Pagina 4.48
EDA-4
Recorrido en profundidad de un grafo
Clasificacion de las aristas. Una arista (u, v) es de tipo:
TREE o del arbol: si el vertice v ha sido descubierto a traves dedicha arista. Estas aristas definen el bosque del recorrido primero enprofundidad, formado por uno o mas arboles.
BACK o hacia atras: si v es un antecesor de u en el arbol del recorridoprimero en profundidad.
FORWARD o hacia adelante: si v es un descendiente de u en el arboldel recorrido primero en profundidad.
CROSS o de cruce: ningun vertice es antecesor del otro.
El recorrido DFS puede ser utilizado para clasificar las aristas a medidaque las va procesando. Cuando desde un vertice u se considera la arista(u, v), se puede observar el color del vertice destino v:
WHITE indica que es una arista del arbol o TREE.
GRAY indica que es una arista hacia atras o BACK.
BLACK indica que es hacia delante o de cruce. Si d[u] < d[v] es haciadelante y si d[u] > d[v] es de cruce.
FI– UPV: Curso 2008/2009 Pagina 4.49
EDA-4
Recorrido en profundidad de un grafo
Relacion de tipo “parentesis”: en la busqueda primero en profundidad,dados dos vertices del grafo u y v, se cumple exactamente una de estastres posibilidades:
los intervalos [d[u], f [u]] y [d[v], f [v]] son enteramente disjuntos. Eneste caso, ni u es descendiente de v en el arbol DFS ni v descendientede u.
el intervalo [d[u], f [u]] esta contenido enteramente dentro del inter-valor [d[v], f [v]] y u es descendiente de v en el arbol DFS.
el intervalo [d[v], f [v]] esta contenido enteramente dentro del intervalor[d[u], f [u]] y v es descendiente de u en el arbol DFS.
La relacion de estos intervalos tambien sirve para clasificar las aristas,ası la arista (u, v) es:
del arbol si d[u] < d[v] < f [v] < f [u]hacia atras si d[v] < d[u] < f [u] < f [v]de cruce si d[v] < f [v] < d[u] < f [u]
FI– UPV: Curso 2008/2009 Pagina 4.50
EDA-4
Orden topologico
Un orden topologico de un grafo dirigido acıclico G = (V,A) es unaordenacion de los vertices de forma que si (u, v) ∈ A, entonces u apareceantes que v. (La solucion no es unica.) Ejem.: prerrequisitos de losestudios.
¡No es posible la ordenacion topologica cuando existen ciclos!
c
b
ed
a
a b d e c
d a e b c
Orden no unico.Ordenacion de vertices en eje horizontal con las aristas de izquierda a derecha.
FI– UPV: Curso 2008/2009 Pagina 4.51
EDA-4
Orden topologico
Dado un grafo G = (V,A), el DFS puede usarse para determinar si esacıclico y, en ese caso, obtener un orden topologico.
El grafo es acıclico si no tiene ninguna arista hacia atras.
El orden en que finaliza la exploracion de los vertices (valor guardadoen f [v]) es un orden topologico invertido.
1 void grafo::dfs_visit(int u) {2 color[u] = GRAY;3 d[u] = ++time;4 for (arista *r = vec[u]; r != 0; r = r->sig) {5 int v = r->vertice_destino;6 if (color[v] == WHITE) { pr[v] = u;7 dfs_visit(v);8 } else if (color[v] == GRAY) es_aciclico = false;9 } // es_aciclico esta a true antes de empezar DFS
10 color[u] = BLACK;11 f[u] = time;12 topologic_sort.push_front(u); // insertar al ppio13 }
FI– UPV: Curso 2008/2009 Pagina 4.52
EDA-4
Recorrido en profundidad de un grafo: Ejemplo 2
Grafo:110 10 21 32 43 23 43 55 74 64 71 81 98 109 10
dfs_visit(0)(0,2) is a TREE EDGEdfs_visit(2)
(2,4) is a TREE EDGEdfs_visit(4)
(4,7) is a TREE EDGEdfs_visit(7)(4,6) is a TREE EDGEdfs_visit(6)
(0,1) is a TREE EDGEdfs_visit(1)
(1,9) is a TREE EDGEdfs_visit(9)
(9,10) is a TREE EDGEdfs_visit(10)
(1,8) is a TREE EDGEdfs_visit(8)
(8,10) is a FORWARD/CROSS EDGE(1,3) is a TREE EDGEdfs_visit(3)
(3,5) is a TREE EDGEdfs_visit(5)
(5,7) is a FORWARD/CROSS EDGE(3,4) is a FORWARD/CROSS EDGE(3,2) is a FORWARD/CROSS EDGE
FI– UPV: Curso 2008/2009 Pagina 4.53
EDA-4
Recorrido en profundidad de un grafo: Ejemplo 2
v d[v] f[v] pr[v]0 1 22 -11 10 21 02 2 9 03 17 20 14 3 8 25 18 19 36 6 7 47 4 5 48 15 16 19 11 14 110 12 13 9
Un posible orden topologico: 0 1 3 5 8 9 10 2 4 6 7
FI– UPV: Curso 2008/2009 Pagina 4.54
EDA-4
Otro algoritmo para el orden topologico, sin DFS
1 void grafo::orden_topologico_sin_dfs() { // test aciclicidad2 int u,v; arista *r;3 for (v=0; v < numVert; ++v) grado_entrada[v] = 0;4 for (v=0; v < numVert; ++v)5 for (r = vec[v]; r != 0; r = r->sig)6 grado_entrada[r->vertice_destino]++;7 col->vaciar();8 for (v=0; v < numVert; v++)9 if (grado_entrada[v] == 0) col->insertar(v);
10 for (n = 0; col->extraer(u); n++) {11 topologic_sort.push_back(u); // insertar al final12 for (arista *r = vec[u]; r != 0; r = r->sig) {13 grado_entrada[r->vertice_destino]--;14 if (grado_entrada[r->vertice_destino] == 0)15 col->insertar(r->vertice_destino);16 }17 }18 es_aciclico = (n == numVert);19 }
FI– UPV: Curso 2008/2009 Pagina 4.55
EDA-4
Recorrido en amplitud de un grafo
Dado un grafo G = (V,A) y un vertice s ∈ V , la estrategia derecorrido en amplitud o en anchura (Breadth-First Search (BFS)),explora sistematicamente las aristas de G de manera que primero sevisitan los vertices mas cercanos a v.
Algunos algoritmos importantes de grafos tienen una estructura similaral BFS. Por ejemplo, el algoritmo de Prim para encontrar el arbol deexpansion de mınimo coste, o el algoritmo de Dijkstra para encontrarlos caminos mas cortos desde un vertice dado.
El algoritmo BFS explora todos los vertices a distancia k del verticeorigen s antes de empezar a explorar los vertices a distancia k + 1.Al igual que DFS, se utiliza un vector de tipo “color” para marcar losvertices del grafo como no visitados (WHITE), visitandose (GRAY) oya visitados (BLACK).
Tambien se genera un vector de predecesores para obtener un arbol.
FI– UPV: Curso 2008/2009 Pagina 4.56
EDA-4
Recorrido en amplitud de un grafo
1 void grafo::bfs(int vertice) {2 cola.clear();3 for (int u=0; u < numVert; ++u) {4 color[u]=WHITE; pr[u]=-1; d[u]=numVert+1;5 // numVert+1> cualquier distancia en el grafo6 }7 cola.push_back(vertice);8 d[vertice] = 0;9 while (!cola.empty()) {
10 int u = cola.front(); cola.pop_front(); // extraer11 for (arista *r = vec[u]; r != 0; r = r->sig) {12 int v = r->vertice_destino;13 if (color[v] == WHITE) {14 color[v]=GRAY; d[v]=d[u]+1; pr[v]=u;15 cola.push_back(v);16 }17 }18 color[u] = BLACK;19 }20 }
FI– UPV: Curso 2008/2009 Pagina 4.57
EDA-4
Recorrido en amplitud de un grafo: Ejemplo
Grafo:110 10 21 32 43 23 43 55 74 64 71 81 98 109 10
FI– UPV: Curso 2008/2009 Pagina 4.58
EDA-4
Recorrido en amplitud de un grafo: Ejemplo
Cola: salen< 0 <entranCola: salen< 2 1 <entranCola: salen< 1 4 <entranCola: salen< 4 9 8 3 <entranCola: salen< 9 8 3 7 6 <entranCola: salen< 8 3 7 6 10 <entranCola: salen< 3 7 6 10 <entranCola: salen< 7 6 10 5 <entranCola: salen< 6 10 5 <entranCola: salen< 10 5 <entranCola: salen< 5 <entran
v d[v] pr[v]0 0 -11 1 02 1 03 2 14 2 25 3 36 3 47 3 48 2 19 2 110 3 9
FI– UPV: Curso 2008/2009 Pagina 4.59