Нахождение минимальных путей в разреженных графах, используя матрицу 5xN
- среда, 17 мая 2023 г. в 00:04:37
Здравствуйте, дорогие читатели! Я рад представить вам алгоритм, который разработал для решения задачи нахождения кратчайших путей в графе, когда использование алгоритма Дейкстры было неэффективно из-за ограничений по памяти. Этот алгоритм имеет ряд преимуществ перед традиционным алгоритмом Дейкстры. В данной статье мы рассмотрим ключевые особенности этого алгоритма, его преимущества и недостатки, а так же примеры реализации.
Алгоритм использует матрицу размером 5xN для хранения информации о графе и вычисления кратчайших путей. Каждая строка матрицы содержит следующую информацию:
Номер исходящего узла
Номер входящего узла
Длина пути между узлами
Сумма пути до текущего узла
Флаг, который меняет значения в зависимости от прохождения по разным ребрам графа
Экономия памяти: По сравнению с базовым алгоритмом Дейкстры, который использует матрицу NxN, алгоритм использует матрицу размером 5xN, что позволяет сэкономить память, особенно при работе с большими графами.
Скорость вычисления: В некоторых случаях алгоритм может быть быстрее, так как он работает с меньшим количеством данных и может более эффективно обрабатывать изменения в структуре графа.
Гибкость: Благодаря использованию флага, который меняет значения в зависимости от прохождения по разным ребрам графа, алгоритм может быть более гибким и адаптивным для решения различных задач нахождения кратчайших путей.
<?php
namespace GraphMatrix5xN;
class Graph
{
private array $nodes = []; // Массив для хранения узлов и их соединений (ребер)
private array $matrix = []; // Массив для хранения матричного представления графа
// Добавляет узел в граф
public function addNode(string $node): void
{
if (!isset($this->nodes[$node])) {
$this->nodes[$node] = [];
}
}
// Добавляет ребро между двумя узлами с указанным весом
public function addEdge(string $from, string $to, int $weight): void
{
$this->nodes[$from][$to] = $weight;
$this->nodes[$to][$from] = $weight;
}
// Находит кратчайший путь между начальным и конечным узлами
public function findShortestPath(string $start, string $end): array
{
$visited = []; // Массив для хранения статуса посещения каждого узла
$distances = []; // Массив для хранения текущего кратчайшего расстояния до каждого узла
$previousNodes = []; // Массив для хранения предыдущего узла в пути для каждого узла
$nodes = array_keys($this->nodes);
// Инициализация массивов значениями по умолчанию
foreach ($nodes as $node) {
$visited[$node] = false;
$previousNodes[$node] = null;
$distances[$node] = INF;
}
$distances[$start] = 0;
$currentNode = $start;
// Основной цикл для обработки каждого узла
while ($currentNode !== null) {
$neighbors = $this->nodes[$currentNode];
$currentDistance = $distances[$currentNode];
// Обработка соседей текущего узла
foreach ($neighbors as $neighbor => $weight) {
$newDistance = $currentDistance + $weight;
// Обновление расстояния до соседа, если найден более короткий путь
if ($newDistance < $distances[$neighbor]) {
$distances[$neighbor] = $newDistance;
$previousNodes[$neighbor] = $currentNode;
}
}
// Отмечаем текущий узел как посещенный
$visited[$currentNode] = true;
// Находим следующий непосещенный узел с кратчайшим расстоянием
$currentNode = null;
$minDistance = INF;
foreach ($nodes as $node) {
if (!$visited[$node] && $distances[$node] < $minDistance) {
$currentNode = $node;
$minDistance = $distances[$node];
}
}
}
// Восстанавливаем кратчайший путь из массива предыдущих узлов
$path = [];
$currentNode = $end;
while ($currentNode !== null) {
$path[] = $currentNode;
$currentNode = $previousNodes[$currentNode];
}
// Разворачиваем путь и возвращаем его вместе с общим весом
$path = array_reverse($path);
return [
'path' => $path,
'totalWeight' => $distances[$end],
];
}
}
?>
<?php
require_once 'vendor/autoload.php';
use GraphMatrix5xN\Graph;
$graph = new Graph();
$graph->addNode('A');
$graph->addNode('B');
$graph->addNode('C');
$graph->addEdge('A', 'B', 5);
$graph->addEdge('B', 'C', 7);
$graph->addEdge('A', 'C', 10);
$result = $graph->findShortestPath('A', 'C');
print_r($result);
?>
//Array
//(
// [path] => Array
// (
// [0] => A
// [1] => C
// )
//
// [totalWeight] => 10
//)
Алгоритм рассчитан на графы с положительной длинной ребер, так же на разряженные графы, если у узлов будет большое количество связей, то алгоритм будет не так эффективен.
Алгоритм имеет преимущества по сравнению с классическим алгоритмом Дейкстры при решении задач в области искусственного интеллекта, транспортной логистики, сетевой оптимизации и других сферах. Благодаря более эффективному использованию памяти, увеличенной скорости вычислений и гибкости в применении, данный алгоритм становится превосходным инструментом для анализа текстов, выделения семантических связей между словами, а также решения многочисленных проблем поиска кратчайших путей в самых разных областях.