En esta sección, pondremos en práctica los conceptos aprendidos sobre grafos mediante una serie de ejercicios. Cada ejercicio está diseñado para reforzar tu comprensión y habilidades en la manipulación y análisis de grafos. Asegúrate de intentar resolver cada ejercicio por tu cuenta antes de consultar las soluciones proporcionadas.
Ejercicio 1: Representación de Grafos
Enunciado
Dado el siguiente grafo no dirigido, represéntalo utilizando una lista de adyacencia y una matriz de adyacencia.
Solución
Lista de Adyacencia
grafo_lista_adyacencia = { 'A': ['B', 'C'], 'B': ['A', 'C', 'D'], 'C': ['A', 'B', 'D'], 'D': ['B', 'C'] }
Matriz de Adyacencia
# A B C D matriz_adyacencia = [ [0, 1, 1, 0], # A [1, 0, 1, 1], # B [1, 1, 0, 1], # C [0, 1, 1, 0] # D ]
Explicación
- Lista de Adyacencia: Cada nodo tiene una lista de nodos a los que está conectado.
- Matriz de Adyacencia: Una matriz donde
matriz_adyacencia[i][j]
es 1 si hay una arista entre el nodoi
y el nodoj
, y 0 en caso contrario.
Ejercicio 2: Implementación de BFS (Breadth-First Search)
Enunciado
Implementa el algoritmo de búsqueda en anchura (BFS) para el siguiente grafo y encuentra el recorrido BFS comenzando desde el nodo 'A'.
Solución
from collections import deque def bfs(grafo, inicio): visitados = set() cola = deque([inicio]) recorrido = [] while cola: nodo = cola.popleft() if nodo not in visitados: visitados.add(nodo) recorrido.append(nodo) cola.extend(grafo[nodo]) return recorrido grafo = { 'A': ['B', 'C'], 'B': ['D'], 'C': ['E'], 'D': ['F'], 'E': ['F'], 'F': [] } print(bfs(grafo, 'A'))
Explicación
- Deque: Utilizamos una cola (
deque
) para mantener el orden de los nodos a visitar. - Visitados: Un conjunto para rastrear los nodos que ya hemos visitado.
- Recorrido: Una lista para almacenar el orden en que visitamos los nodos.
Resultado
Ejercicio 3: Implementación de DFS (Depth-First Search)
Enunciado
Implementa el algoritmo de búsqueda en profundidad (DFS) para el siguiente grafo y encuentra el recorrido DFS comenzando desde el nodo 'A'.
Solución
def dfs(grafo, inicio, visitados=None): if visitados is None: visitados = set() visitados.add(inicio) recorrido = [inicio] for vecino in grafo[inicio]: if vecino not in visitados: recorrido.extend(dfs(grafo, vecino, visitados)) return recorrido grafo = { 'A': ['B', 'C'], 'B': ['D'], 'C': ['E'], 'D': ['F'], 'E': ['F'], 'F': [] } print(dfs(grafo, 'A'))
Explicación
- Recursión: Utilizamos la recursión para explorar cada nodo y sus vecinos.
- Visitados: Un conjunto para rastrear los nodos que ya hemos visitado.
- Recorrido: Una lista para almacenar el orden en que visitamos los nodos.
Resultado
Ejercicio 4: Algoritmo de Dijkstra
Enunciado
Implementa el algoritmo de Dijkstra para encontrar el camino más corto desde el nodo 'A' al nodo 'F' en el siguiente grafo ponderado.
Solución
import heapq def dijkstra(grafo, inicio): distancias = {nodo: float('inf') for nodo in grafo} distancias[inicio] = 0 cola_prioridad = [(0, inicio)] camino = {} while cola_prioridad: distancia_actual, nodo_actual = heapq.heappop(cola_prioridad) if distancia_actual > distancias[nodo_actual]: continue for vecino, peso in grafo[nodo_actual].items(): distancia = distancia_actual + peso if distancia < distancias[vecino]: distancias[vecino] = distancia camino[vecino] = nodo_actual heapq.heappush(cola_prioridad, (distancia, vecino)) return distancias, camino grafo = { 'A': {'B': 1, 'C': 4}, 'B': {'C': 2, 'D': 5}, 'C': {'D': 1, 'E': 3}, 'D': {'F': 2}, 'E': {'F': 1}, 'F': {} } distancias, camino = dijkstra(grafo, 'A') print("Distancias:", distancias) print("Camino:", camino)
Explicación
- Heapq: Utilizamos una cola de prioridad (
heapq
) para seleccionar el nodo con la menor distancia. - Distancias: Un diccionario para almacenar la distancia mínima desde el nodo inicial a cada nodo.
- Camino: Un diccionario para rastrear el camino más corto.
Resultado
Distancias: {'A': 0, 'B': 1, 'C': 3, 'D': 4, 'E': 6, 'F': 6} Camino: {'B': 'A', 'C': 'B', 'D': 'C', 'F': 'D'}
Conclusión
En esta sección, hemos practicado la representación de grafos, así como la implementación de algoritmos fundamentales como BFS, DFS y Dijkstra. Estos ejercicios te ayudarán a consolidar tu comprensión de los grafos y sus aplicaciones en la programación. Asegúrate de revisar y entender cada solución antes de pasar al siguiente módulo.
Curso de Estructuras de Datos
Módulo 1: Introducción a las Estructuras de Datos
- ¿Qué son las Estructuras de Datos?
- Importancia de las Estructuras de Datos en la Programación
- Tipos de Estructuras de Datos
Módulo 2: Listas
- Introducción a las Listas
- Listas Enlazadas
- Listas Doblemente Enlazadas
- Listas Circulares
- Ejercicios con Listas
Módulo 3: Pilas
- Introducción a las Pilas
- Operaciones Básicas con Pilas
- Implementación de Pilas
- Aplicaciones de las Pilas
- Ejercicios con Pilas
Módulo 4: Colas
- Introducción a las Colas
- Operaciones Básicas con Colas
- Colas Circulares
- Colas de Prioridad
- Ejercicios con Colas
Módulo 5: Árboles
- Introducción a los Árboles
- Árboles Binarios
- Árboles Binarios de Búsqueda
- Árboles AVL
- Árboles B
- Ejercicios con Árboles
Módulo 6: Grafos
- Introducción a los Grafos
- Representación de Grafos
- Algoritmos de Búsqueda en Grafos
- Algoritmos de Caminos Mínimos
- Aplicaciones de los Grafos
- Ejercicios con Grafos