Iniciamos el tutorial de grafos aclarando el vocabulario y los motivos por los cuales esta estructura es tan flexible en C. 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 C 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:
#include <stdio.h>
int main(void) {
int n = 4;
int matriz[4][4] = {
{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 */
printf("0 y 2 son vecinos? %s\n", matriz[0][2] ? "si" : "no");
return 0;
}
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 C y avanzar hacia algoritmos de recorrido, búsqueda y optimización sobre grafos.