Iniciamos el tutorial de grafos aclarando el vocabulario y los motivos por los cuales esta estructura es tan flexible en Python. A diferencia de las estructuras lineales o jerárquicas, los grafos modelan relaciones arbitrarias y permiten capturar redes, mapas, dependencias y flujos.
Este capítulo define qué es un grafo, la terminología básica, los tipos de problemas que habilita y varias aplicaciones reales que justifican dominarlo.
Un grafo es un par G = (V, E) donde V es un conjunto finito de vértices (o nodos) y E es un conjunto de aristas que conectan pares de vértices. Las aristas pueden ser:
En Python es habitual representar un grafo con una matriz de adyacencia o una lista de adyacencia. El siguiente ejemplo muestra una matriz de adyacencia para un grafo no dirigido con 4 vértices:
n = 4
matriz = [
[0, 1, 0, 1], # conexiones del vertice 0
[1, 0, 1, 0],
[0, 1, 0, 1],
[1, 0, 1, 0],
]
# Verificamos si 0 y 2 son adyacentes
print("0 y 2 son vecinos?", "si" if matriz[0][2] else "no")
Una matriz de adyacencia es un arreglo cuadrado de tamaño n x n donde n es la cantidad de vértices. Cada posición [u][v] indica si existe una arista entre los vértices u y v; en grafos no dirigidos la matriz es simétrica y la diagonal suele quedar en 0. Si almacenamos pesos, el valor numérico representa la distancia o costo de la conexión. Su consumo de memoria es O(n), por lo que resulta práctica en grafos densos (muchas aristas) y menos conveniente en grafos poco poblados.
El valor 1 indica la existencia de una arista entre dos vértices. En la matriz del ejemplo no hay arista directa entre 0 y 2 (el valor es 0), por eso la salida imprime no. Aun así, 0 puede llegar a 2 siguiendo dos saltos: primero hasta 1 y luego hasta 2 (0 → 1 → 2), o primero hasta 3 y luego hasta 2 (0 → 3 → 2). Con pequeñas variaciones este modelo soporta grafos dirigidos (matriz asimétrica) y grafos ponderados (almacenando el peso en lugar de 0/1).
Usaremos los siguientes términos de forma consistente a lo largo del tutorial:
matriz[u][v] != 0.Gracias a su flexibilidad, los grafos permiten modelar y resolver problemas variados:
Los grafos aparecen en numerosos dominios prácticos:
Con estos conceptos cubiertos podremos implementar representaciones en Python y avanzar hacia algoritmos de recorrido, búsqueda y optimización sobre grafos.