Portada
Presentación
(reemplazar este texto por título).
Ingeniería en
Computación
#IC
ALGORITMOS Y
ESTRUCTURAS
DE DATOS
ALGORITMOS
Y
ESTRUCTURAS
DE DATOS
#IC
#IC
● Grafos
● Representaciones
● Matrices de Adyacencia
● Listas de Adyacencia
● Objetos
● Camino más corto y Distancia mínima
● Algoritmo de Dijkstra
● Algoritmo de Floyd
● Árbol recubridor mínimo
● Algoritmo de Kruskal
● Algoritmo de Prim
● Ejercicios
AGENDA
#IC
GRAFOS
La ciudad de Königsberg, en Prusia, tenía 7 puentes.
¿Existe alguna forma de atravesar la ciudad pasando
por cada puente una sola vez?
#IC
GRAFOS
Un grafo es una representación
de relaciones entre pares de
objetos.
A cada uno de esos objetos se
los denomina nodo o vértice.
Las conexiones entre nodos se
denominan aristas o arcos.
#IC
GRAFOS
Las aristas de un grafo pueden
ser dirigidas si tiene un origen
y un destino definido. Si no,
las aristas se denominan no
dirigidas.
El grafo será clasificado como
dirigido o no dirigido,
dependiendo de las
características de sus aristas.
#IC
GRAFOS
Además de una dirección, las
aristas pueden tener asociados
valores llamados pesos.
Dos nodos pueden estar
conectados por más de una
arista, cada una con su peso
determinado.
Los pesos de que conectan dos
nodos en sentidos opuestos
también pueden diferir
#IC
CAMINOS
• Un camino es la secuencia de nodos y aristas que
unen dos nodos particulares.
• En un grafo dirigido, si existe un camino que una el
nodo u con el nodo v, se dice que “el nodo v es
accesible desde el nodo u”.
• Por más que v sea accesible desde u, no
necesariamente se da la relación inversa.
• En un grafo no dirigido, se dice que los nodos están
conectados.
#IC
REPRESENTACIONES
• Existen 3 formas de representación :
• Matrices de adyacencia
• Listas de adyacencia
• Listas anidadas
• Diccionarios
• Objetos
#IC
MATRICES DE ADYACENCIA
• A cada nodo de un grafo se le asigna
un número desde 0 hasta V, siendo V el
número de nodos en el grafo.
• Se construye una matriz de tamaño V *
V, donde:
Aij
1si iy jestán conectados
0 en otro caso
Aij
el peso de la uniónentre iy j
0 en otro caso
Grafos no pesados Grafos pesados
#IC
MATRICES DE ADYACENCIA
Indice Aeropuerto
0 SFO
1 BOS
2 JFK
3 ORD
4 DFW
5 LAX
6 MIA
#IC
MATRICES DE ADYACENCIA
0 1 2 3 4 5 6
0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 1
2 1 0 0 0 1 0 1
3 0 0 0 0 1 0 0
4 0 0 0 1 0 1 0
5 0 0 0 1 0 0 0
6 0 0 0 0 1 1 0
#IC
MATRICES DE ADYACENCIA
sfo = [0, 0, 0, 0, 0, 0, 0]
bos = [1, 0, 0, 0, 0, 0, 1]
jfk = [1, 0, 0, 0, 1, 0, 1]
ord = [0, 0, 0, 0, 1, 0, 0]
dfw = [0, 0, 0, 1, 0, 1, 0]
lax = [0, 0, 0, 1, 0, 0, 0]
mia = [0, 0, 0, 0, 1, 1, 0]
matriz_ady = [sfo, bos, jfk, ord, dfw, lax, mia]
print('ORD - DFW: ', matriz_ady[3][4])
#IC
MATRICES DE ADYACENCIA
sfo = [0, 0, 0, 0, 0, 0, 0]
bos = [75, 0, 0, 0, 0, 0, 205]
jfk = [365, 0, 0, 0, 225, 0, 175]
ord = [0, 0, 0, 0, 145, 0, 0]
dfw = [0, 0, 0, 132, 0, 200, 0]
lax = [0, 0, 0, 230, 0, 0, 0]
mia = [0, 0, 0, 0, 185, 300, 0]
matriz_ady = [sfo, bos, jfk, ord, dfw, lax, mia]
print('ORD - DFW: ', matriz_ady[3][4])
#IC
LISTAS DE ADYACENCIA
• Los grafos también pueden representarse
como múltiples listas, una por cada nodo.
• Cada lista posee todos los nodos conectados
al nodo correspondiente.
• En Python, dado que no existe nativamente el
tipo de dato “matriz”, las implementaciones
de matrices y listas de adyacencias son muy
similares.
#IC
LISTAS DE ADYACENCIA
sfo = []
bos = ['JFK', 'MIA']
jfk = ['SFO', 'DFW', 'MIA']
ord = ['DFW']
dfw = ['ORD', 'LAX']
lax = ['ORD']
mia = ['DFW', 'LAX']
lista_ady = [sfo, bos, jfk, ord, dfw, lax, mia]
for i in lista_ady[3]:
if i =='DFW':
print(True)
#IC
LISTAS DE ADYACENCIA
• Las listas de
adyacencia también
pueden
implementarse
usando
diccionarios.
• Esta estrategia hace
más simple acceder
a los distintos
nodos.
dicc_ady = {'SFO': {},
'BOS': {'JFK': 75, 'MIA': 205},
'JFK': {'SFO': 365, 'DFW': 225, 'MIA': 175},
'ORD': {'DFW': 145},
'DFW': {'ORD': 135, 'LAX': 200},
'LAX': {'ORD': 230},
'MIA': {'DFW': 185, 'LAX': 330}
}
print('ORD-DFW: ', dicc_ady['ORD']['DFW'])
#IC
OBJETOS
• Otra forma de implementar grafos es definiendo
clases específicas para nodos y aristas.
• La clase nodo contiene el elemento del nodo.
• Dependiendo del tipo de grafo, la clase arista va
a contener distintos elementos:
• Origen
• Destino
• Peso
• …
#IC
RECORRIDO DE GRAFOS
• Similar a los árboles, los recorridos pueden ser por
anchura o por profundidad.
• En el recorrido por anchura, se define el nodo de
comienzo y se añaden todos los nodos unidos a él a
una cola.
• Los siguientes nodos se recorren siguiendo el orden en
la cola.
• Se debe llevar la cuenta de qué nodos ya fueron
visitados, para no entrar en bucles infinitos.
#IC
RECORRIDO POR ANCHURA
Entrada: grafo, nodo inicio.
agregar inicio a la cola de nodo por visitar
mientras que haya nodos en la cola:
quitar nodo de la cola
agregar nodo a la lista de visitados
por cada nodo conectado a nodo visitando:
si no fue visitado, agregar a la cola de nodos por
visitar
#IC
RECORRIDO POR ANCHURA
def anchura(grafo, inicio):
cola = [inicio]
visitados = []
while len(cola) != 0:
visitando = cola.pop(0)
if visitando not in visitados:
visitados.append(visitando)
for n in grafo[visitando]:
cola.append(n)
return visitados
#IC
RECORRIDO POR PROFUNDIDAD
• En el recorrido por profundidad, se
define el nodo de comienzo y,
recursivamente, se visitan todos los
nodos conectados a ese inicio.
• Nuevamente, se debe llevar la cuenta de
qué nodos ya fueron visitados, para no
entrar en bucles infinitos.
#IC
RECORRIDO POR PROFUNDIDAD
Entrada: grafo, nodo inicio, lista visitados.
agregar inicio a visitados
por cada nodo conectado a nodo visitando:
si nodo no está en visitados:
visitar(grafo, nodo, visitados)
devolver visitados
#IC
RECORRIDO POR PROFUNDIDAD
def profundidad(grafo, inicio, visitados = []):
visitados.append(inicio)
for n in grafo[inicio]:
if n not in visitados:
visitados = profundidad(grafo, n, visitados)
return visitados
#IC
CAMINO MÁS CORTO
• Un camino es la
secuencia de
nodos y aristas que
unen dos nodos
particulares.
• El peso de un
camino es la suma
de todos los pesos
que lo componen.
Caminos entre “JFK” y “LAX”:
● 'JFK', 'DFW', 'LAX': 425
● 'JFK', 'MIA', 'DFW', 'LAX': 560
● 'JFK', 'MIA', 'LAX': 505
#IC
CAMINO MÁS CORTO
• Para calcular todas las distancias de un nodo
a los otros, se podría seguir una estrategia de
fuerza bruta:
• Elegir un nodo inicio.
• Para cada nodo n dentro del grafo,
calcular todas las distancias desde inicio
hasta n.
• Elegir la menor distancia dentro de todos
los resultados.
#IC
CAMINO MÁS CORTO
• Para Una forma de optimizar el código sería
aplicando la estrategia de la poda.
• Elegir un nodo inicio.
• Para cada nodo n dentro del grafo,
calcular cada distancia desde inicio hasta
n.
• Si la distancia intermedia es mayor a la
distancia menor conocida, no continuar.
#IC
ALGORITMO DE DIJKSTRA
• El algoritmo de Dijkstra permite calcular el menor
camino desde un inicio a todos los nodos de un grafo.
• Es un algoritmo ávido que consiste en calcular las
distancias desde un nodo a los adyacentes, y continuar
el cálculo desde el nodo de menor distancia.
• El algoritmo comienza con el nodo de inicio y termina
cuando todos los nodos accesibles fueron visitados.
• Para cada nodo n se almacena la distancia mínima
desde el inicio y el nodo anterior que conduce a n.
#IC
ALGORITMO DE DIJKSTRA
Nodo Distancia Anterior
JFK 0 None
BOS Inf -
SFO Inf -
MIA Inf -
ORD Inf -
DFW Inf -
LAX Inf -
Actual = “JFK”
Visitados = [“JFK”]
#IC
ALGORITMO DE DIJKSTRA
Actual = “JFK”
Visitados = [“JFK”]
¿D > D
mia jfk-mia
?
¿Inf > 175 ?
Nodo Distancia Anterior
JFK 0 None
BOS Inf -
SFO Inf -
MIA Inf -
ORD Inf -
DFW Inf -
LAX Inf -
#IC
ALGORITMO DE DIJKSTRA
Actual = “JFK”
Visitados = [“JFK”]
Nodo Distancia Anterior
JFK 0 None
BOS Inf -
SFO 365 JFK
MIA 175 JFK
ORD Inf -
DFW 225 JFK
LAX Inf -
#IC
ALGORITMO DE DIJKSTRA
Actual = “MIA”
Visitados = [“JFK”,”MIA”]
Nodo Distancia Anterior
JFK 0 None
BOS Inf -
SFO 365 JFK
MIA 175 JFK
ORD Inf -
DFW 225 JFK
LAX Inf -
#IC
ALGORITMO DE DIJKSTRA
Actual = “MIA”
Visitados = [“JFK”,”MIA”]
¿D > D + D
dfw jfk-mia mia-dfw
?
¿225 > 175 + 185 ?
Nodo Distancia Anterior
JFK 0 None
BOS Inf -
SFO 365 JFK
MIA 175 JFK
ORD Inf -
DFW 225 JFK
LAX 475 MIA
#IC
ALGORITMO DE DIJKSTRA
Actual = “DFW”
Visitados = [“JFK”,”MIA”]
¿D > D + D
lax jfk-dfw dfw-lax
?
¿475 > 225 + 200 ?
Nodo Distancia Anterior
JFK 0 None
BOS Inf -
SFO 365 JFK
MIA 175 JFK
ORD 132 DFW
DFW 225 JFK
LAX 475 MIA
#IC
ALGORITMO DE DIJKSTRA
Actual = “DFW”
Visitados = [“JFK”,”MIA”]
Nodo Distancia Anterior
JFK 0 None
BOS Inf -
SFO 365 JFK
MIA 175 JFK
ORD 357 DFW
DFW 225 JFK
LAX 445 DFW
#IC
ALGORITMO DE DIJKSTRA
Actual = “ORD”
Visitados = [“JFK”,”MIA”,”DFW”]
Nodo Distancia Anterior
JFK 0 None
BOS Inf -
SFO 365 JFK
MIA 175 JFK
ORD 357 DFW
DFW 225 JFK
LAX 445 DFW
#IC
ALGORITMO DE DIJKSTRA
Actual = “SFO”
Visitados = [“JFK”,”MIA”,”DFW”,”ORD”]
Nodo Distancia Anterior
JFK 0 None
BOS Inf -
SFO 365 JFK
MIA 175 JFK
ORD 357 DFW
DFW 225 JFK
LAX 445 DFW
#IC
ALGORITMO DE DIJKSTRA
Actual = “LAX”
Visitados = [“JFK”,”MIA”,”DFW”,”ORD”,”SFO”]
Nodo Distancia Anterior
JFK 0 None
BOS Inf -
SFO 365 JFK
MIA 175 JFK
ORD 357 DFW
DFW 225 JFK
LAX 445 DFW
#IC
ALGORITMO DE DIJKSTRA
Entrada: grafo, nodo inicio
Inicializar tabla de resultados con distancias y anteriores:
Si n == inicio:
distancia = 0
anterior = None
Si no:
distancia = Inf
anterior = None
Inicializar nodo actual = inicio
Inicializar lista visitados como lista vacía
#IC
ALGORITMO DE DIJKSTRA
Mientras que actual no sea None:
Agregar actual a visitados
Por cada nodo n adyacente a actual:
Calcular distancia desde n a inicio pasando por actual
(almacenado en tabla de resultados)
Si la distancia nueva es menor a la conocida:
actualizar valores
Elegir siguiente nodo
Si existe:
menor distancia dentro de resultados y que no haya sido visitado
Sino
retornar None
#IC
ALGORITMO DE DIJKSTRA
def distancia_menor(resultados, visitados):
dist = float('inf')
nodo = None
for r in resultados:
if resultados[r]["Distancia"] < dist and r not in visitados:
dist = resultados[r]["Distancia"]
nodo = r
return nodo
#IC
ALGORITMO DE DIJKSTRA
def dijkstra(grafo, inicio):
actual = inicio
visitados = []
resultados = {}
for g in grafo:
if g == inicio:
resultados[g] = {"Distancia": 0, "Anterior": None}
else:
resultados[g] = {"Distancia": float("inf"), "Anterior": None}
while actual != None:
visitados.append(actual)
for g in grafo[actual]:
if resultados[g]["Distancia"] > resultados[actual]["Distancia"] + grafo[actual][g]:
resultados[g]["Distancia"] = resultados[actual]["Distancia"] + grafo[actual][g]
resultados[g]["Anterior"] = actual
actual = distancia_menor(resultados, visitados)
return resultados
#IC
RECONSTRUYENDO EL CAMINO MÍNIMO
Para encontrar el camino
mínimo a un nodo, se debe
recorrer la lista de nodos
anteriores hasta llegar al inicio.
Por ejemplo, el camino
hasta “ORD” se calcularía
cómo:
“ORD”
“DFW” (anterior a “ORD”)
“JFK” (anterior a “DFW”)
Nodo Distancia Anterior
JFK 0 None
BOS Inf -
SFO 365 JFK
MIA 175 JFK
ORD
357
DFW
DFW 225 JFK
LAX 445 DFW
#IC
RECONSTRUYENDO EL CAMINO MÍNIMO
def recontruir_camino(resultados, inicio, fin):
camino = []
actual = fin
while actual != inicio:
camino = [actual] + camino
actual = resultados[actual]["Anterior"]
camino = [inicio] + camino
return camino
#IC
DISTANCIA MÍNIMA
• El algoritmo de Diijkstra permite encontrar
las distancias de un nodo particular al resto
de los nodos accesibles.
• Si se quisieran conocer todas las distancias,
se debería ejecutar el código n veces.
• Una alternativa para disminuir el número de
cálculos es el algoritmo de Floyd.
#IC
ALGORITMO DE FLOYD
• El algoritmo de Floyd utiliza una matriz de adyacencia para
calcular las distancias entre todos los pares de nodos.
• Este algoritmo tiene muchas coincidencias con el algoritmo
de Dijkstra.
• Para facilitar los cálculos, al comienzo las distancias entre
nodos no adyacentes se establece como infinita.
• Luego se recorre la matriz completa y se comprueba si la
distancia conocida entre dos nodos es mayor a la
distancia entre esos nodos, pasando por un nodo
adicional:
¿ Dij > Dik + Dkj ?
#IC
ALGORITMO DE FLOYD
SFO BOS JFK ORD DFW LAX MIA
SFO 0 Inf Inf Inf Inf Inf Inf
BOS Inf 0 75 Inf Inf Inf 205
JFK 365 Inf 0 Inf 225 Inf 175
ORD Inf Inf Inf 0 145 Inf Inf
DFW Inf Inf Inf 132 0 200 Inf
LAX Inf Inf Inf 230 Inf 0 Inf
MIA Inf Inf Inf Inf 185 300 0
i
j
Calculando la distancia mínima entre BOS y SFO:
i = 1;j = 0; D10 = Inf
k = 0: D10 = Inf; D00 = 0 => No cambiar
k = 1: D11 = 0; D10 = Inf => No cambiar
k = 2: D12 = 75; D20 = 365 => Cambiar
Dij = 440
k = 3: D13 = Inf; D30 = Inf => No cambiar
k = 4: D14 = Inf; D40 = Inf => No cambiar
k = 5: D15 = Inf; D50 = Inf => No cambiar
k = 6: D16 = 205; D60 = Inf => No cambiar
#IC
ALGORITMO DE FLOYD
SFO BOS JFK ORD DFW LAX MIA
SFO 0 Inf Inf Inf Inf Inf Inf
BOS Inf 0 75 Inf Inf Inf 205
JFK 365 Inf 0 Inf 225 Inf 175
ORD Inf Inf Inf 0 145 Inf Inf
DFW Inf Inf Inf 132 0 200 Inf
LAX Inf Inf Inf 230 Inf 0 Inf
MIA Inf Inf Inf Inf 185 300 0
i
j Calculando la distancia mínima entre JFK y LAX:
i = 2; j = 5; D25 = Inf
k = 0: D20 = 365; D05 = Inf => No cambiar
k = 1: D21 = Inf; D15 = Inf => No cambiar
k = 2: D22 = 0; D25 = Inf => No cambiar
k = 3: D23 = Inf; D35 = Inf => No cambiar
k = 4: D24 = 225; D45 = 200 => Cambiar
Dij = 425
k = 5: D25 = Inf; D55 = Inf => No cambiar
k = 6: D26 = 175; D65 = 300 => No cambiar
#IC
ALGORITMO DE FLOYD
Entrada: matriz de adyacencia con 0,
distancias e infinitos
Para cada nodo intermedio (k):
Para cada nodo de inicio (i):
Para cada nodo de fin (j):
Calcular Dij y la suma entre Dik y Dkj
Si corresponde, actualizar valores
#IC
ALGORITMO DE FLOYD
def preparar_matriz(matriz):
for i in range (0, len(matriz)):
for j in range (0, len(matriz)):
if i != j and matriz[i][j] == 0:
matriz[i][j] = float("inf")
return matriz
def floyd(matriz):
for k in range (0, len(matriz)):
for i in range (0, len(matriz)):
for j in range (0, len(matriz)):
if matriz[i][j] > matriz[i][k] + matriz[k][j]:
matriz[i][j] = matriz[i][k] + matriz[k][j]
return matriz
#IC
ÁRBOL RECUBRIDOR MÍNIMO
Se desean conectar en red todas las
computadoras de un aula.
¿Cómo podría calcular el orden en que
deberían conectarse para utilizar la
menor cantidad de cable posible?
#IC
ÁRBOL RECUBRIDOR MÍNIMO
• Un árbol recubridor contiene
todos los nodos de un grafo
no dirigido y conectado.
• Si el grafo posee n nodos, el
árbol recubridor posee n-1
aristas.
• El árbol recubridor mínimo es
el árbol con menor peso total.
#IC
ALGORITMO DE KRUSKAL
• Es un algoritmo ávido.
• La heurística en la que se basa es seleccionar el arco de
menor peso.
• A medida que se seleccionan nodos, se van formando
distintos subárboles, que serán combinados en un árbol
final.
• Si la arista de menor peso conecta nodos ya presentes en un
mismo árbol, se descarta.
• El algoritmo termina cuando se forma un solo árbol de n-1
aristas.
#IC
ALGORITMO DE KRUSKAL
#IC
ALGORITMO DE KRUSKAL
#IC
ALGORITMO DE KRUSKAL
#IC
ALGORITMO DE KRUSKAL
#IC
ALGORITMO DE KRUSKAL
#IC
ALGORITMO DE KRUSKAL
#IC
ALGORITMO DE KRUSKAL
#IC
ALGORITMO DE KRUSKAL
#IC
ALGORITMO DE KRUSKAL
#IC
ALGORITMO DE KRUSKAL
Entrada: grafo, no dirigido, ponderado
armar tabla de pesos, ordenada
mientras que el número de aristas en el árbol != n-1:
elegir arista de menor peso, quitar de la lista
si los nodos no están en ningún subárbol:
crear subárbol
si están en distintos subárboles:
combinar subárboles
si están en el mismo árbol:
descartar arista
#IC
ALGORITMO DE PRIM
• También es un algoritmo ávido.
• Se comienza eligiendo la arista de menor peso, y se
continúa con la arista de menor peso conectada a los
nodos ya visitados.
• Si la arista de menor peso lleva a un nodo ya visitado, se
descarta.
• El algoritmo termina cuando todos los nodos fueron
visitados
#IC
ALGORITMO DE PRIM
#IC
ALGORITMO DE PRIM
#IC
ALGORITMO DE PRIM
#IC
ALGORITMO DE PRIM
#IC
ALGORITMO DE PRIM
#IC
ALGORITMO DE PRIM
#IC
ALGORITMO DE PRIM
#IC
ALGORITMO DE PRIM
#IC
ALGORITMO DE PRIM
#IC
ALGORITMO DE PRIM
Entrada: grafo, no dirigido, ponderado
seleccionar arista de menor peso
añadir arista la árbol, nodos a la lista de visitados
mientras queden nodos por visitar:
seleccionar arista de menor peso conectada a nodos
visitados
si el nodo de destino no fue visitado:
añadir arista al árbol, nodo de destino a lista de visitados
#IC
ALGORITMO DE KRUSKAL
from operator import itemgetter
def kruskal (grafo):
arm = {}
arboles = []
aristas = 0
lista_ordenada = ordenar_lista(grafo)
while aristas != len(grafo)-1:
inicio, fin, peso = lista_ordenada.pop(0)
agregar = anadir_nodos(arboles, inicio, fin)
if agregar == True:
print(inicio, fin, peso)
aristas += 1
if inicio not in arm:
arm[inicio] = {}
arm[inicio][fin] = peso
return arm
def ordenar_lista (grafo):
resultado = []
for i in grafo:
for f in grafo[i]:
resultado.append((i, f, grafo[i][f]))
resultado.sort(key=itemgetter(2))
return resultado
#IC
ALGORITMO DE KRUSKAL
def anadir_nodos(arboles, inicio, fin):
indice_inicio = indice_fin = None
for i in range(0, len(arboles)):
if inicio in arboles[i]:
indice_inicio = i
if fin in arboles[i]:
indice_fin = i
if indice_inicio == None and indice_fin != None:
arboles[indice_fin].append(inicio)
return True
elif indice_inicio != None and indice_fin == None:
arboles[indice_inicio].append(fin)
return True
elif indice_inicio == None and indice_fin == None:
arboles.append([inicio, fin])
return True
elif indice_inicio != None and indice_fin != None and indice_inicio != indice_fin:
arboles.append(arboles[indice_inicio]+arboles[indice_fin])
quitar_inicio = arboles[indice_inicio]
quitar_fin = arboles[indice_fin]
arboles.remove(quitar_inicio)
arboles.remove(quitar_fin)
return True
#IC
ALGORITMO DE PRIM
def prim (grafo):
arm = {} visitados = []
while len(visitados) < len(grafo):
inicio, fin, peso = encontrar_arista_menor(grafo, visitados)
print(inicio, fin, peso)
if inicio not in visitados:
visitados.append(inicio)
if fin not in visitados:
visitados.append(fin)
if inicio not in arm:
arm[inicio] = {}
arm[inicio][fin] = peso
return arm
#IC
ALGORITMO DE PRIM
def encontrar_arista_menor (grafo, visitados):
nodo_inicio = ""
nodo_fin = ""
menor_peso = float("inf")
if len(visitados) == 0:
for inicio in grafo:
for fin in grafo[inicio]:
if grafo[inicio][fin] < menor_peso:
menor_peso = grafo[inicio][fin]
nodo_inicio = inicio
nodo_fin = fin
else:
for inicio in visitados:
for fin in grafo[inicio]:
if grafo[inicio][fin] < menor_peso and fin not in visitados:
menor_peso = grafo[inicio][fin]
nodo_inicio = inicio
nodo_fin = fin
return nodo_inicio, nodo_fin, menor_peso
#IC
EJERCICIOS
#IC
#IC
EJERCICIO 1
A partir del siguiente grafo, calcule los árboles recubridores
mínimos usando los algoritmos de Kruskal y de Prim.
A
B
H G
C D
F
I E
4
8 7
1
1 2
6
1
8
2
4
14
9
10
7
#IC
10.Grafos.y.Algoritmos.Avanzados.para.Grafos.pdf

Más contenido relacionado

PDF
Grafos-2021.pdf
ODP
Bfs en grafos
ODP
Bfs en grafos
ODP
Bfs en grafos
ODP
Bfs en grafos
ODP
Bfs en grafos
ODP
Bfs en grafos
PPTX
Codemotion 2016 - d3.js un taller divertido y difícil
Grafos-2021.pdf
Bfs en grafos
Bfs en grafos
Bfs en grafos
Bfs en grafos
Bfs en grafos
Bfs en grafos
Codemotion 2016 - d3.js un taller divertido y difícil

Similar a 10.Grafos.y.Algoritmos.Avanzados.para.Grafos.pdf (20)

PPT
Grafos
PPT
Grafos
PPT
Grafos
PPT
2 punteros y lenguaje c
PDF
Semana 4 Javascript funciones y Metodos
PPT
elementaryAlgorithms.ppt
DOCX
Métodos Trabajo de Búsqueda 02 - IA.docx
PDF
Arboles.pdf
PPTX
Algoritmo de dijkstra final
PDF
Tutorial arduino 03 programación
PPTX
Análisis de algoritmos
TXT
Coloreo
PDF
estudio de desarrolode estraucturade dat
PDF
Tutorial arduino 03 programacin
PDF
Tutorial arduino 03 programacin
PPTX
PDF
Introducción al mundo NoSQL
PDF
Fun[ctional] spark with scala
PPT
1 árbol
PPTX
1: funciones matematicas y cadena de caracteres 2:operacion de asignacion: ar...
Grafos
Grafos
Grafos
2 punteros y lenguaje c
Semana 4 Javascript funciones y Metodos
elementaryAlgorithms.ppt
Métodos Trabajo de Búsqueda 02 - IA.docx
Arboles.pdf
Algoritmo de dijkstra final
Tutorial arduino 03 programación
Análisis de algoritmos
Coloreo
estudio de desarrolode estraucturade dat
Tutorial arduino 03 programacin
Tutorial arduino 03 programacin
Introducción al mundo NoSQL
Fun[ctional] spark with scala
1 árbol
1: funciones matematicas y cadena de caracteres 2:operacion de asignacion: ar...
Publicidad

Último (20)

PDF
MATERIAL DIDÁCTICO 2023 SELECCIÓN 1_REFORZAMIENTO 1° BIMESTRE_COM.pdf
PDF
Modelo Educativo SUB 2023versión final.pdf
PDF
ACERTIJO EL CONJURO DEL CAZAFANTASMAS MATEMÁTICO. Por JAVIER SOLIS NOYOLA
PPTX
Historia-Clinica-de-Emergencia-Obstetrica 1.10.pptx
PDF
informe tipos de Informatica perfiles profesionales _pdf
PPTX
TEMA 1ORGANIZACIÓN FUNCIONAL DEL CUERPO, MEDIO INTERNO Y HOMEOSTASIS (3) [Aut...
DOC
Manual de Convivencia 2025 actualizado a las normas vigentes
PDF
LIBRO 2-SALUD Y AMBIENTE-4TO CEBA avanzado.pdf
PDF
2.0 Introduccion a processing, y como obtenerlo
PDF
Introduccion a la Investigacion Cualitativa FLICK Ccesa007.pdf
DOCX
PLANES DE área ciencias naturales y aplicadas
PPTX
4. Qué es un computador PARA GRADO CUARTO.pptx
PDF
Esc. Sab. Lección 7. El pan y el agua de vida.pdf
PDF
Texto Digital Los Miserables - Victor Hugo Ccesa007.pdf
PDF
MODULO I ENFERMERIA BASICA.pdf HIstoria en enfermeria
PDF
RM2025 - FUNDAMENTOS TEÓRICOS - PEDIATRÍA.pdf
PPTX
BIZANCIO. EVOLUCIÓN HISTORICA, RAGOS POLÍTICOS, ECONOMICOS Y SOCIALES
DOCX
Programa_Sintetico_Fase_4.docx 3° Y 4°..
PDF
ciencia_tecnologia_sociedad Mitcham Carl. (1994)..pdf
PPTX
RESUMENES JULIO - QUIRÓFANO HOSPITAL GENERAL PUYO.pptx
MATERIAL DIDÁCTICO 2023 SELECCIÓN 1_REFORZAMIENTO 1° BIMESTRE_COM.pdf
Modelo Educativo SUB 2023versión final.pdf
ACERTIJO EL CONJURO DEL CAZAFANTASMAS MATEMÁTICO. Por JAVIER SOLIS NOYOLA
Historia-Clinica-de-Emergencia-Obstetrica 1.10.pptx
informe tipos de Informatica perfiles profesionales _pdf
TEMA 1ORGANIZACIÓN FUNCIONAL DEL CUERPO, MEDIO INTERNO Y HOMEOSTASIS (3) [Aut...
Manual de Convivencia 2025 actualizado a las normas vigentes
LIBRO 2-SALUD Y AMBIENTE-4TO CEBA avanzado.pdf
2.0 Introduccion a processing, y como obtenerlo
Introduccion a la Investigacion Cualitativa FLICK Ccesa007.pdf
PLANES DE área ciencias naturales y aplicadas
4. Qué es un computador PARA GRADO CUARTO.pptx
Esc. Sab. Lección 7. El pan y el agua de vida.pdf
Texto Digital Los Miserables - Victor Hugo Ccesa007.pdf
MODULO I ENFERMERIA BASICA.pdf HIstoria en enfermeria
RM2025 - FUNDAMENTOS TEÓRICOS - PEDIATRÍA.pdf
BIZANCIO. EVOLUCIÓN HISTORICA, RAGOS POLÍTICOS, ECONOMICOS Y SOCIALES
Programa_Sintetico_Fase_4.docx 3° Y 4°..
ciencia_tecnologia_sociedad Mitcham Carl. (1994)..pdf
RESUMENES JULIO - QUIRÓFANO HOSPITAL GENERAL PUYO.pptx
Publicidad

10.Grafos.y.Algoritmos.Avanzados.para.Grafos.pdf

  • 1. Portada Presentación (reemplazar este texto por título). Ingeniería en Computación #IC ALGORITMOS Y ESTRUCTURAS DE DATOS
  • 3. #IC
  • 4. #IC ● Grafos ● Representaciones ● Matrices de Adyacencia ● Listas de Adyacencia ● Objetos ● Camino más corto y Distancia mínima ● Algoritmo de Dijkstra ● Algoritmo de Floyd ● Árbol recubridor mínimo ● Algoritmo de Kruskal ● Algoritmo de Prim ● Ejercicios AGENDA
  • 5. #IC GRAFOS La ciudad de Königsberg, en Prusia, tenía 7 puentes. ¿Existe alguna forma de atravesar la ciudad pasando por cada puente una sola vez?
  • 6. #IC GRAFOS Un grafo es una representación de relaciones entre pares de objetos. A cada uno de esos objetos se los denomina nodo o vértice. Las conexiones entre nodos se denominan aristas o arcos.
  • 7. #IC GRAFOS Las aristas de un grafo pueden ser dirigidas si tiene un origen y un destino definido. Si no, las aristas se denominan no dirigidas. El grafo será clasificado como dirigido o no dirigido, dependiendo de las características de sus aristas.
  • 8. #IC GRAFOS Además de una dirección, las aristas pueden tener asociados valores llamados pesos. Dos nodos pueden estar conectados por más de una arista, cada una con su peso determinado. Los pesos de que conectan dos nodos en sentidos opuestos también pueden diferir
  • 9. #IC CAMINOS • Un camino es la secuencia de nodos y aristas que unen dos nodos particulares. • En un grafo dirigido, si existe un camino que una el nodo u con el nodo v, se dice que “el nodo v es accesible desde el nodo u”. • Por más que v sea accesible desde u, no necesariamente se da la relación inversa. • En un grafo no dirigido, se dice que los nodos están conectados.
  • 10. #IC REPRESENTACIONES • Existen 3 formas de representación : • Matrices de adyacencia • Listas de adyacencia • Listas anidadas • Diccionarios • Objetos
  • 11. #IC MATRICES DE ADYACENCIA • A cada nodo de un grafo se le asigna un número desde 0 hasta V, siendo V el número de nodos en el grafo. • Se construye una matriz de tamaño V * V, donde: Aij 1si iy jestán conectados 0 en otro caso Aij el peso de la uniónentre iy j 0 en otro caso Grafos no pesados Grafos pesados
  • 12. #IC MATRICES DE ADYACENCIA Indice Aeropuerto 0 SFO 1 BOS 2 JFK 3 ORD 4 DFW 5 LAX 6 MIA
  • 13. #IC MATRICES DE ADYACENCIA 0 1 2 3 4 5 6 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 2 1 0 0 0 1 0 1 3 0 0 0 0 1 0 0 4 0 0 0 1 0 1 0 5 0 0 0 1 0 0 0 6 0 0 0 0 1 1 0
  • 14. #IC MATRICES DE ADYACENCIA sfo = [0, 0, 0, 0, 0, 0, 0] bos = [1, 0, 0, 0, 0, 0, 1] jfk = [1, 0, 0, 0, 1, 0, 1] ord = [0, 0, 0, 0, 1, 0, 0] dfw = [0, 0, 0, 1, 0, 1, 0] lax = [0, 0, 0, 1, 0, 0, 0] mia = [0, 0, 0, 0, 1, 1, 0] matriz_ady = [sfo, bos, jfk, ord, dfw, lax, mia] print('ORD - DFW: ', matriz_ady[3][4])
  • 15. #IC MATRICES DE ADYACENCIA sfo = [0, 0, 0, 0, 0, 0, 0] bos = [75, 0, 0, 0, 0, 0, 205] jfk = [365, 0, 0, 0, 225, 0, 175] ord = [0, 0, 0, 0, 145, 0, 0] dfw = [0, 0, 0, 132, 0, 200, 0] lax = [0, 0, 0, 230, 0, 0, 0] mia = [0, 0, 0, 0, 185, 300, 0] matriz_ady = [sfo, bos, jfk, ord, dfw, lax, mia] print('ORD - DFW: ', matriz_ady[3][4])
  • 16. #IC LISTAS DE ADYACENCIA • Los grafos también pueden representarse como múltiples listas, una por cada nodo. • Cada lista posee todos los nodos conectados al nodo correspondiente. • En Python, dado que no existe nativamente el tipo de dato “matriz”, las implementaciones de matrices y listas de adyacencias son muy similares.
  • 17. #IC LISTAS DE ADYACENCIA sfo = [] bos = ['JFK', 'MIA'] jfk = ['SFO', 'DFW', 'MIA'] ord = ['DFW'] dfw = ['ORD', 'LAX'] lax = ['ORD'] mia = ['DFW', 'LAX'] lista_ady = [sfo, bos, jfk, ord, dfw, lax, mia] for i in lista_ady[3]: if i =='DFW': print(True)
  • 18. #IC LISTAS DE ADYACENCIA • Las listas de adyacencia también pueden implementarse usando diccionarios. • Esta estrategia hace más simple acceder a los distintos nodos. dicc_ady = {'SFO': {}, 'BOS': {'JFK': 75, 'MIA': 205}, 'JFK': {'SFO': 365, 'DFW': 225, 'MIA': 175}, 'ORD': {'DFW': 145}, 'DFW': {'ORD': 135, 'LAX': 200}, 'LAX': {'ORD': 230}, 'MIA': {'DFW': 185, 'LAX': 330} } print('ORD-DFW: ', dicc_ady['ORD']['DFW'])
  • 19. #IC OBJETOS • Otra forma de implementar grafos es definiendo clases específicas para nodos y aristas. • La clase nodo contiene el elemento del nodo. • Dependiendo del tipo de grafo, la clase arista va a contener distintos elementos: • Origen • Destino • Peso • …
  • 20. #IC RECORRIDO DE GRAFOS • Similar a los árboles, los recorridos pueden ser por anchura o por profundidad. • En el recorrido por anchura, se define el nodo de comienzo y se añaden todos los nodos unidos a él a una cola. • Los siguientes nodos se recorren siguiendo el orden en la cola. • Se debe llevar la cuenta de qué nodos ya fueron visitados, para no entrar en bucles infinitos.
  • 21. #IC RECORRIDO POR ANCHURA Entrada: grafo, nodo inicio. agregar inicio a la cola de nodo por visitar mientras que haya nodos en la cola: quitar nodo de la cola agregar nodo a la lista de visitados por cada nodo conectado a nodo visitando: si no fue visitado, agregar a la cola de nodos por visitar
  • 22. #IC RECORRIDO POR ANCHURA def anchura(grafo, inicio): cola = [inicio] visitados = [] while len(cola) != 0: visitando = cola.pop(0) if visitando not in visitados: visitados.append(visitando) for n in grafo[visitando]: cola.append(n) return visitados
  • 23. #IC RECORRIDO POR PROFUNDIDAD • En el recorrido por profundidad, se define el nodo de comienzo y, recursivamente, se visitan todos los nodos conectados a ese inicio. • Nuevamente, se debe llevar la cuenta de qué nodos ya fueron visitados, para no entrar en bucles infinitos.
  • 24. #IC RECORRIDO POR PROFUNDIDAD Entrada: grafo, nodo inicio, lista visitados. agregar inicio a visitados por cada nodo conectado a nodo visitando: si nodo no está en visitados: visitar(grafo, nodo, visitados) devolver visitados
  • 25. #IC RECORRIDO POR PROFUNDIDAD def profundidad(grafo, inicio, visitados = []): visitados.append(inicio) for n in grafo[inicio]: if n not in visitados: visitados = profundidad(grafo, n, visitados) return visitados
  • 26. #IC CAMINO MÁS CORTO • Un camino es la secuencia de nodos y aristas que unen dos nodos particulares. • El peso de un camino es la suma de todos los pesos que lo componen. Caminos entre “JFK” y “LAX”: ● 'JFK', 'DFW', 'LAX': 425 ● 'JFK', 'MIA', 'DFW', 'LAX': 560 ● 'JFK', 'MIA', 'LAX': 505
  • 27. #IC CAMINO MÁS CORTO • Para calcular todas las distancias de un nodo a los otros, se podría seguir una estrategia de fuerza bruta: • Elegir un nodo inicio. • Para cada nodo n dentro del grafo, calcular todas las distancias desde inicio hasta n. • Elegir la menor distancia dentro de todos los resultados.
  • 28. #IC CAMINO MÁS CORTO • Para Una forma de optimizar el código sería aplicando la estrategia de la poda. • Elegir un nodo inicio. • Para cada nodo n dentro del grafo, calcular cada distancia desde inicio hasta n. • Si la distancia intermedia es mayor a la distancia menor conocida, no continuar.
  • 29. #IC ALGORITMO DE DIJKSTRA • El algoritmo de Dijkstra permite calcular el menor camino desde un inicio a todos los nodos de un grafo. • Es un algoritmo ávido que consiste en calcular las distancias desde un nodo a los adyacentes, y continuar el cálculo desde el nodo de menor distancia. • El algoritmo comienza con el nodo de inicio y termina cuando todos los nodos accesibles fueron visitados. • Para cada nodo n se almacena la distancia mínima desde el inicio y el nodo anterior que conduce a n.
  • 30. #IC ALGORITMO DE DIJKSTRA Nodo Distancia Anterior JFK 0 None BOS Inf - SFO Inf - MIA Inf - ORD Inf - DFW Inf - LAX Inf - Actual = “JFK” Visitados = [“JFK”]
  • 31. #IC ALGORITMO DE DIJKSTRA Actual = “JFK” Visitados = [“JFK”] ¿D > D mia jfk-mia ? ¿Inf > 175 ? Nodo Distancia Anterior JFK 0 None BOS Inf - SFO Inf - MIA Inf - ORD Inf - DFW Inf - LAX Inf -
  • 32. #IC ALGORITMO DE DIJKSTRA Actual = “JFK” Visitados = [“JFK”] Nodo Distancia Anterior JFK 0 None BOS Inf - SFO 365 JFK MIA 175 JFK ORD Inf - DFW 225 JFK LAX Inf -
  • 33. #IC ALGORITMO DE DIJKSTRA Actual = “MIA” Visitados = [“JFK”,”MIA”] Nodo Distancia Anterior JFK 0 None BOS Inf - SFO 365 JFK MIA 175 JFK ORD Inf - DFW 225 JFK LAX Inf -
  • 34. #IC ALGORITMO DE DIJKSTRA Actual = “MIA” Visitados = [“JFK”,”MIA”] ¿D > D + D dfw jfk-mia mia-dfw ? ¿225 > 175 + 185 ? Nodo Distancia Anterior JFK 0 None BOS Inf - SFO 365 JFK MIA 175 JFK ORD Inf - DFW 225 JFK LAX 475 MIA
  • 35. #IC ALGORITMO DE DIJKSTRA Actual = “DFW” Visitados = [“JFK”,”MIA”] ¿D > D + D lax jfk-dfw dfw-lax ? ¿475 > 225 + 200 ? Nodo Distancia Anterior JFK 0 None BOS Inf - SFO 365 JFK MIA 175 JFK ORD 132 DFW DFW 225 JFK LAX 475 MIA
  • 36. #IC ALGORITMO DE DIJKSTRA Actual = “DFW” Visitados = [“JFK”,”MIA”] Nodo Distancia Anterior JFK 0 None BOS Inf - SFO 365 JFK MIA 175 JFK ORD 357 DFW DFW 225 JFK LAX 445 DFW
  • 37. #IC ALGORITMO DE DIJKSTRA Actual = “ORD” Visitados = [“JFK”,”MIA”,”DFW”] Nodo Distancia Anterior JFK 0 None BOS Inf - SFO 365 JFK MIA 175 JFK ORD 357 DFW DFW 225 JFK LAX 445 DFW
  • 38. #IC ALGORITMO DE DIJKSTRA Actual = “SFO” Visitados = [“JFK”,”MIA”,”DFW”,”ORD”] Nodo Distancia Anterior JFK 0 None BOS Inf - SFO 365 JFK MIA 175 JFK ORD 357 DFW DFW 225 JFK LAX 445 DFW
  • 39. #IC ALGORITMO DE DIJKSTRA Actual = “LAX” Visitados = [“JFK”,”MIA”,”DFW”,”ORD”,”SFO”] Nodo Distancia Anterior JFK 0 None BOS Inf - SFO 365 JFK MIA 175 JFK ORD 357 DFW DFW 225 JFK LAX 445 DFW
  • 40. #IC ALGORITMO DE DIJKSTRA Entrada: grafo, nodo inicio Inicializar tabla de resultados con distancias y anteriores: Si n == inicio: distancia = 0 anterior = None Si no: distancia = Inf anterior = None Inicializar nodo actual = inicio Inicializar lista visitados como lista vacía
  • 41. #IC ALGORITMO DE DIJKSTRA Mientras que actual no sea None: Agregar actual a visitados Por cada nodo n adyacente a actual: Calcular distancia desde n a inicio pasando por actual (almacenado en tabla de resultados) Si la distancia nueva es menor a la conocida: actualizar valores Elegir siguiente nodo Si existe: menor distancia dentro de resultados y que no haya sido visitado Sino retornar None
  • 42. #IC ALGORITMO DE DIJKSTRA def distancia_menor(resultados, visitados): dist = float('inf') nodo = None for r in resultados: if resultados[r]["Distancia"] < dist and r not in visitados: dist = resultados[r]["Distancia"] nodo = r return nodo
  • 43. #IC ALGORITMO DE DIJKSTRA def dijkstra(grafo, inicio): actual = inicio visitados = [] resultados = {} for g in grafo: if g == inicio: resultados[g] = {"Distancia": 0, "Anterior": None} else: resultados[g] = {"Distancia": float("inf"), "Anterior": None} while actual != None: visitados.append(actual) for g in grafo[actual]: if resultados[g]["Distancia"] > resultados[actual]["Distancia"] + grafo[actual][g]: resultados[g]["Distancia"] = resultados[actual]["Distancia"] + grafo[actual][g] resultados[g]["Anterior"] = actual actual = distancia_menor(resultados, visitados) return resultados
  • 44. #IC RECONSTRUYENDO EL CAMINO MÍNIMO Para encontrar el camino mínimo a un nodo, se debe recorrer la lista de nodos anteriores hasta llegar al inicio. Por ejemplo, el camino hasta “ORD” se calcularía cómo: “ORD” “DFW” (anterior a “ORD”) “JFK” (anterior a “DFW”) Nodo Distancia Anterior JFK 0 None BOS Inf - SFO 365 JFK MIA 175 JFK ORD 357 DFW DFW 225 JFK LAX 445 DFW
  • 45. #IC RECONSTRUYENDO EL CAMINO MÍNIMO def recontruir_camino(resultados, inicio, fin): camino = [] actual = fin while actual != inicio: camino = [actual] + camino actual = resultados[actual]["Anterior"] camino = [inicio] + camino return camino
  • 46. #IC DISTANCIA MÍNIMA • El algoritmo de Diijkstra permite encontrar las distancias de un nodo particular al resto de los nodos accesibles. • Si se quisieran conocer todas las distancias, se debería ejecutar el código n veces. • Una alternativa para disminuir el número de cálculos es el algoritmo de Floyd.
  • 47. #IC ALGORITMO DE FLOYD • El algoritmo de Floyd utiliza una matriz de adyacencia para calcular las distancias entre todos los pares de nodos. • Este algoritmo tiene muchas coincidencias con el algoritmo de Dijkstra. • Para facilitar los cálculos, al comienzo las distancias entre nodos no adyacentes se establece como infinita. • Luego se recorre la matriz completa y se comprueba si la distancia conocida entre dos nodos es mayor a la distancia entre esos nodos, pasando por un nodo adicional: ¿ Dij > Dik + Dkj ?
  • 48. #IC ALGORITMO DE FLOYD SFO BOS JFK ORD DFW LAX MIA SFO 0 Inf Inf Inf Inf Inf Inf BOS Inf 0 75 Inf Inf Inf 205 JFK 365 Inf 0 Inf 225 Inf 175 ORD Inf Inf Inf 0 145 Inf Inf DFW Inf Inf Inf 132 0 200 Inf LAX Inf Inf Inf 230 Inf 0 Inf MIA Inf Inf Inf Inf 185 300 0 i j Calculando la distancia mínima entre BOS y SFO: i = 1;j = 0; D10 = Inf k = 0: D10 = Inf; D00 = 0 => No cambiar k = 1: D11 = 0; D10 = Inf => No cambiar k = 2: D12 = 75; D20 = 365 => Cambiar Dij = 440 k = 3: D13 = Inf; D30 = Inf => No cambiar k = 4: D14 = Inf; D40 = Inf => No cambiar k = 5: D15 = Inf; D50 = Inf => No cambiar k = 6: D16 = 205; D60 = Inf => No cambiar
  • 49. #IC ALGORITMO DE FLOYD SFO BOS JFK ORD DFW LAX MIA SFO 0 Inf Inf Inf Inf Inf Inf BOS Inf 0 75 Inf Inf Inf 205 JFK 365 Inf 0 Inf 225 Inf 175 ORD Inf Inf Inf 0 145 Inf Inf DFW Inf Inf Inf 132 0 200 Inf LAX Inf Inf Inf 230 Inf 0 Inf MIA Inf Inf Inf Inf 185 300 0 i j Calculando la distancia mínima entre JFK y LAX: i = 2; j = 5; D25 = Inf k = 0: D20 = 365; D05 = Inf => No cambiar k = 1: D21 = Inf; D15 = Inf => No cambiar k = 2: D22 = 0; D25 = Inf => No cambiar k = 3: D23 = Inf; D35 = Inf => No cambiar k = 4: D24 = 225; D45 = 200 => Cambiar Dij = 425 k = 5: D25 = Inf; D55 = Inf => No cambiar k = 6: D26 = 175; D65 = 300 => No cambiar
  • 50. #IC ALGORITMO DE FLOYD Entrada: matriz de adyacencia con 0, distancias e infinitos Para cada nodo intermedio (k): Para cada nodo de inicio (i): Para cada nodo de fin (j): Calcular Dij y la suma entre Dik y Dkj Si corresponde, actualizar valores
  • 51. #IC ALGORITMO DE FLOYD def preparar_matriz(matriz): for i in range (0, len(matriz)): for j in range (0, len(matriz)): if i != j and matriz[i][j] == 0: matriz[i][j] = float("inf") return matriz def floyd(matriz): for k in range (0, len(matriz)): for i in range (0, len(matriz)): for j in range (0, len(matriz)): if matriz[i][j] > matriz[i][k] + matriz[k][j]: matriz[i][j] = matriz[i][k] + matriz[k][j] return matriz
  • 52. #IC ÁRBOL RECUBRIDOR MÍNIMO Se desean conectar en red todas las computadoras de un aula. ¿Cómo podría calcular el orden en que deberían conectarse para utilizar la menor cantidad de cable posible?
  • 53. #IC ÁRBOL RECUBRIDOR MÍNIMO • Un árbol recubridor contiene todos los nodos de un grafo no dirigido y conectado. • Si el grafo posee n nodos, el árbol recubridor posee n-1 aristas. • El árbol recubridor mínimo es el árbol con menor peso total.
  • 54. #IC ALGORITMO DE KRUSKAL • Es un algoritmo ávido. • La heurística en la que se basa es seleccionar el arco de menor peso. • A medida que se seleccionan nodos, se van formando distintos subárboles, que serán combinados en un árbol final. • Si la arista de menor peso conecta nodos ya presentes en un mismo árbol, se descarta. • El algoritmo termina cuando se forma un solo árbol de n-1 aristas.
  • 64. #IC ALGORITMO DE KRUSKAL Entrada: grafo, no dirigido, ponderado armar tabla de pesos, ordenada mientras que el número de aristas en el árbol != n-1: elegir arista de menor peso, quitar de la lista si los nodos no están en ningún subárbol: crear subárbol si están en distintos subárboles: combinar subárboles si están en el mismo árbol: descartar arista
  • 65. #IC ALGORITMO DE PRIM • También es un algoritmo ávido. • Se comienza eligiendo la arista de menor peso, y se continúa con la arista de menor peso conectada a los nodos ya visitados. • Si la arista de menor peso lleva a un nodo ya visitado, se descarta. • El algoritmo termina cuando todos los nodos fueron visitados
  • 75. #IC ALGORITMO DE PRIM Entrada: grafo, no dirigido, ponderado seleccionar arista de menor peso añadir arista la árbol, nodos a la lista de visitados mientras queden nodos por visitar: seleccionar arista de menor peso conectada a nodos visitados si el nodo de destino no fue visitado: añadir arista al árbol, nodo de destino a lista de visitados
  • 76. #IC ALGORITMO DE KRUSKAL from operator import itemgetter def kruskal (grafo): arm = {} arboles = [] aristas = 0 lista_ordenada = ordenar_lista(grafo) while aristas != len(grafo)-1: inicio, fin, peso = lista_ordenada.pop(0) agregar = anadir_nodos(arboles, inicio, fin) if agregar == True: print(inicio, fin, peso) aristas += 1 if inicio not in arm: arm[inicio] = {} arm[inicio][fin] = peso return arm def ordenar_lista (grafo): resultado = [] for i in grafo: for f in grafo[i]: resultado.append((i, f, grafo[i][f])) resultado.sort(key=itemgetter(2)) return resultado
  • 77. #IC ALGORITMO DE KRUSKAL def anadir_nodos(arboles, inicio, fin): indice_inicio = indice_fin = None for i in range(0, len(arboles)): if inicio in arboles[i]: indice_inicio = i if fin in arboles[i]: indice_fin = i if indice_inicio == None and indice_fin != None: arboles[indice_fin].append(inicio) return True elif indice_inicio != None and indice_fin == None: arboles[indice_inicio].append(fin) return True elif indice_inicio == None and indice_fin == None: arboles.append([inicio, fin]) return True elif indice_inicio != None and indice_fin != None and indice_inicio != indice_fin: arboles.append(arboles[indice_inicio]+arboles[indice_fin]) quitar_inicio = arboles[indice_inicio] quitar_fin = arboles[indice_fin] arboles.remove(quitar_inicio) arboles.remove(quitar_fin) return True
  • 78. #IC ALGORITMO DE PRIM def prim (grafo): arm = {} visitados = [] while len(visitados) < len(grafo): inicio, fin, peso = encontrar_arista_menor(grafo, visitados) print(inicio, fin, peso) if inicio not in visitados: visitados.append(inicio) if fin not in visitados: visitados.append(fin) if inicio not in arm: arm[inicio] = {} arm[inicio][fin] = peso return arm
  • 79. #IC ALGORITMO DE PRIM def encontrar_arista_menor (grafo, visitados): nodo_inicio = "" nodo_fin = "" menor_peso = float("inf") if len(visitados) == 0: for inicio in grafo: for fin in grafo[inicio]: if grafo[inicio][fin] < menor_peso: menor_peso = grafo[inicio][fin] nodo_inicio = inicio nodo_fin = fin else: for inicio in visitados: for fin in grafo[inicio]: if grafo[inicio][fin] < menor_peso and fin not in visitados: menor_peso = grafo[inicio][fin] nodo_inicio = inicio nodo_fin = fin return nodo_inicio, nodo_fin, menor_peso
  • 80. #IC
  • 82. #IC EJERCICIO 1 A partir del siguiente grafo, calcule los árboles recubridores mínimos usando los algoritmos de Kruskal y de Prim. A B H G C D F I E 4 8 7 1 1 2 6 1 8 2 4 14 9 10 7
  • 83. #IC