Поиск в графе

Mind.js — это библиотека для построения и анализа графов и сетей в JavaScript. Она предоставляет функционал для создания узлов, ребер, весов и различных алгоритмов поиска, включая поиск в глубину, поиск в ширину и алгоритмы кратчайшего пути. Работа с графами в Mind.js строится вокруг двух ключевых сущностей: Node и Graph.

  • Node — представляет отдельную точку графа, может содержать идентификатор, данные и ссылку на соседние узлы.
  • Graph — структура, объединяющая узлы и ребра, поддерживает ориентированные и неориентированные графы, хранит веса ребер.
const { Graph, Node } = require('mindjs');

const graph = new Graph();
const nodeA = new Node('A');
const nodeB = new Node('B');

graph.addNode(nodeA);
graph.addNode(nodeB);
graph.addEdge(nodeA, nodeB, { weight: 5 });

Здесь создаётся граф с двумя узлами и ребром с весом 5, направленным от A к B. Вес ребра используется в алгоритмах поиска кратчайшего пути.

Алгоритмы поиска

Mind.js реализует несколько базовых алгоритмов обхода графа. Каждый из них оптимизирован под разные задачи.

Поиск в ширину (Breadth-First Search, BFS)

BFS применяется для нахождения кратчайшего пути по количеству ребер в неориентированных и ориентированных графах без учёта веса. Алгоритм использует очередь и посещает узлы по уровням, начиная с исходного.

const bfsResult = graph.bfs(nodeA, nodeB);
console.log(bfsResult.path); // массив узлов, представляющий путь

Особенности:

  • Гарантирует нахождение минимального числа переходов до целевого узла.
  • Работает корректно даже при циклах благодаря системе пометки посещённых узлов.
  • Подходит для поиска ближайших соседей.

Поиск в глубину (Depth-First Search, DFS)

DFS исследует граф рекурсивно, продвигаясь как можно глубже по каждому пути. Использует стек для хранения текущего пути.

const dfsResult = graph.dfs(nodeA, nodeB);
console.log(dfsResult.path); // путь от nodeA к nodeB

Особенности:

  • Может найти путь к цели быстрее в графах с малой шириной.
  • Используется для проверки связности графа и обнаружения циклов.
  • Не гарантирует кратчайший путь в терминах количества переходов.

Алгоритм Дейкстры

Для поиска кратчайшего пути с учётом веса ребер применяется алгоритм Дейкстры. Mind.js предоставляет встроенную реализацию, которая автоматически учитывает веса.

const dijkstraResult = graph.dijkstra(nodeA, nodeB);
console.log(dijkstraResult.distance); // минимальное расстояние
console.log(dijkstraResult.path); // массив узлов для минимального пути

Ключевые моменты:

  • Требует положительных весов ребер.
  • Оптимизирован для больших графов с произвольной структурой.
  • Позволяет вычислять кратчайшие пути от одного узла ко всем остальным.

Работа с взвешенными и невзвешенными графами

Mind.js различает два типа графов:

  1. Невзвешенные графы — вес ребра игнорируется при BFS и DFS.
  2. Взвешенные графы — вес используется для алгоритмов Дейкстры и других алгоритмов оптимизации.
const weightedGraph = new Graph({ directed: true, weighted: true });
weightedGraph.addEdge(nodeA, nodeB, { weight: 10 });
  • Параметр directed определяет направленность ребер.
  • Параметр weighted указывает, что вес ребер имеет значение для алгоритмов поиска.

Визуализация и анализ графов

Mind.js поддерживает методы для обхода графа и анализа его структуры:

  • graph.nodes — возвращает все узлы графа.
  • graph.edges — возвращает все ребра с весами.
  • graph.degree(node) — количество связей узла.
  • graph.neighbors(node) — массив соседних узлов.

Пример анализа:

const neighborsOfA = graph.neighbors(nodeA);
const degreeOfA = graph.degree(nodeA);
console.log(neighborsOfA, degreeOfA);

Эти методы позволяют быстро получить информацию о связности, плотности и центральности узлов.

Примеры сложных сценариев поиска

  1. Поиск кратчайшего пути с несколькими целями:
const targets = [nodeB, nodeC];
const paths = targets.map(target => graph.dijkstra(nodeA, target).path);
console.log(paths);
  1. Поиск всех возможных маршрутов между двумя узлами:
const allPaths = graph.findAllPaths(nodeA, nodeB);
console.log(allPaths); // массив массивов узлов
  1. Поиск циклов и проверка связности:
const cycles = graph.findCycles();
const isConnected = graph.isConnected();
console.log(cycles, isConnected);

Mind.js позволяет создавать как простые, так и сложные структуры графов, интегрировать весовые параметры и использовать разнообразные алгоритмы поиска без необходимости вручную реализовывать сложные алгоритмы.