La teoría de grafos permite representar objetos y las conexiones que existen entre ellos. En programación, esta idea ayuda a modelar redes, rutas, dependencias, recomendaciones y muchos otros problemas reales.
La teoría de grafos es una rama de la matemática que estudia conjuntos de objetos y las relaciones que los conectan. Estos objetos se representan mediante vértices, también llamados nodos, y las relaciones mediante aristas.
Un mapa de carreteras, una red social y las dependencias de un proyecto de software parecen sistemas diferentes. Sin embargo, todos pueden describirse de la misma forma: hay elementos y existen conexiones entre algunos de ellos.
En este curso utilizaremos JavaScript para transformar estas ideas matemáticas en estructuras de datos y algoritmos ejecutables.
Un grafo se define habitualmente como un par de conjuntos. El conjunto V contiene los vértices y el conjunto E contiene las aristas que relacionan esos vértices.
Por ejemplo, podemos representar tres ciudades mediante V = {A, B, C}. Si hay una carretera entre A y B, y otra entre B y C, las conexiones son E = {{A, B}, {B, C}}.
El grafo no necesita guardar todos los detalles del mundo real. Conserva únicamente los objetos y relaciones necesarios para resolver el problema que nos interesa.
La misma estructura abstracta puede utilizarse en contextos muy distintos. Lo que cambia es el significado de sus vértices y aristas.
| Sistema | Vértices | Aristas |
|---|---|---|
| Red social | Personas | Amistades o seguimientos |
| Mapa | Ciudades o intersecciones | Rutas o calles |
| Sitio web | Páginas | Enlaces |
| Proyecto de software | Módulos o tareas | Dependencias |
| Red informática | Equipos y routers | Conexiones de comunicación |
Podemos comenzar con dos arreglos: uno para los vértices y otro para las aristas. Cada arista se representa como un par de nombres.
const vertices = ["Ana", "Bruno", "Carla", "Diego"];
const aristas = [
["Ana", "Bruno"],
["Ana", "Carla"],
["Bruno", "Diego"]
];
console.log("Vértices:", vertices.length);
console.log("Aristas:", aristas.length);
Este pequeño grafo podría representar una red de amistades. Los cuatro nombres son los vértices y cada par indica una conexión. Más adelante aprenderemos representaciones más eficientes para consultar y recorrer grafos.
Antes de programar conviene identificar qué elementos son importantes y qué tipo de relación existe entre ellos.
| Pregunta | Decisión de modelado | Ejemplo |
|---|---|---|
| ¿Cuáles son los objetos? | Definir los vértices | Estaciones de una red de metro |
| ¿Qué relación los conecta? | Definir las aristas | Dos estaciones consecutivas |
| ¿La relación tiene dirección? | Elegir el tipo de grafo | Una calle de sentido único |
| ¿La relación tiene un costo? | Agregar un peso | Tiempo de viaje entre estaciones |
| ¿Qué necesitamos descubrir? | Elegir un algoritmo | La ruta de menor duración |
Guardar datos no es suficiente: normalmente queremos responder preguntas sobre sus relaciones. Un grafo convierte esas conexiones en información que puede explorarse mediante algoritmos.
Estas preguntas requieren algoritmos diferentes, pero todas parten de la misma representación mediante vértices y aristas.
A partir del grafo anterior podemos crear una función sencilla que determine si dos personas están conectadas directamente.
const amistades = [
["Ana", "Bruno"],
["Ana", "Carla"],
["Bruno", "Diego"]
];
function sonAmigos(persona1, persona2) {
return amistades.some(([a, b]) =>
(a === persona1 && b === persona2) ||
(a === persona2 && b === persona1)
);
}
console.log(sonAmigos("Ana", "Carla"));
console.log(sonAmigos("Carla", "Diego"));
El primer resultado es true porque hay una arista directa entre Ana y Carla. El segundo es false: que ambas pertenezcan al grafo no significa que estén conectadas directamente.
Dos vértices pueden estar relacionados de forma directa mediante una arista o de forma indirecta mediante una secuencia de aristas. Esa secuencia recibe el nombre de camino.
Ana y Diego no tienen una arista directa en el ejemplo, pero existe un camino entre ellos a través de Bruno. Distinguir entre conexión directa y alcanzabilidad es fundamental en buscadores, mapas, redes y sistemas de recomendaciones.
Los grafos proporcionan un vocabulario común para problemas basados en relaciones. Una vez que un sistema se modela como grafo, podemos aplicar algoritmos conocidos en lugar de diseñar una solución completamente nueva para cada caso.
| Área | Problema representado | Resultado buscado |
|---|---|---|
| Navegación y logística | Calles, ciudades y distancias | Encontrar la mejor ruta |
| Redes sociales | Usuarios y relaciones | Recomendar contactos o detectar comunidades |
| Motores de búsqueda | Páginas y enlaces | Estimar relevancia y descubrir contenido |
| Compiladores | Archivos y dependencias | Determinar el orden de compilación |
| Videojuegos | Zonas transitables y movimientos | Guiar personajes por el escenario |
| Inteligencia artificial | Estados, conocimientos o relaciones | Buscar soluciones y realizar inferencias |
Un grafo es una buena elección cuando las relaciones entre los datos son tan importantes como los datos mismos. También resulta útil cuando debemos recorrer conexiones, encontrar rutas o analizar cómo una modificación se propaga por un sistema.
No todos los problemas necesitan grafos. Para una colección simple sin relaciones puede bastar un arreglo; para búsquedas directas por clave, un mapa o diccionario suele ser más adecuado. El objetivo no es usar grafos siempre, sino reconocer cuándo el problema tiene una estructura de red.
La teoría de grafos ofrece una forma sencilla y poderosa de pensar sistemas conectados. Al separar un problema en objetos y relaciones podemos representar situaciones muy diferentes con una estructura común y analizarlas mediante algoritmos.
En el próximo tema conoceremos la historia de la teoría de grafos, desde el problema de los puentes de Königsberg hasta su presencia en la informática actual.