在现实生活中,例如在地图导航、游戏中,都可能存在许多障碍,如何实现最短路径的通达是我们必须考虑的。
我们可以考虑一个具有多个障碍物的 2D 网格,
如下图:我们从源单元格(下面红色)开始到达目标单元格(下面绿色),如何通过算法最快找到最短的直达路程,这就是我们今天要实现的。
什么是Dijkstra 算法?
Dijkstra 算法,也称为单源最短路径,解决了查找从图中的点(源)到目的地的最短路径的问题。它是一种贪婪算法,类似于 Prim 的算法。算法从源顶点 s 开始,它长出一棵树 T,最终跨越从 S 可到达的所有顶点,顶点按距离顺序添加到 T,即首先是 S,然后是最接近 S 的顶点,然后是下一个最接近的顶点,依此类推。
$INT_MAX = 0x7FFFFFFF;
function MinimumDistance($distance, $shortestPathTreeSet, $verticesCount)
{
global $INT_MAX;
$min = $INT_MAX;
$minIndex = 0;
for ($v = 0; $v < $verticesCount; ++$v)
{
if ($shortestPathTreeSet[$v] == false && $distance[$v] <= $min)
{
$min = $distance[$v];
$minIndex = $v;
}
}
return $minIndex;
}
function PrintResult($distance, $verticesCount)
{
echo "<pre>" . "Vertex Distance from source" . "</pre>";
for ($i = 0; $i < $verticesCount; ++$i)
echo "<pre>" . $i . "\t " . $distance[$i] . "</pre>";
}
function Dijkstra($graph, $source, $verticesCount)
{
global $INT_MAX;
$distance = array();
$shortestPathTreeSet = array();
for ($i = 0; $i < $verticesCount; ++$i)
{
$distance[$i] = $INT_MAX;
$shortestPathTreeSet[$i] = false;
}
$distance[$source] = 0;
for ($count = 0; $count < $verticesCount - 1; ++$count)
{
$u = MinimumDistance($distance, $shortestPathTreeSet, $verticesCount);
$shortestPathTreeSet[$u] = true;
for ($v = 0; $v < $verticesCount; ++$v)
if (!$shortestPathTreeSet[$v] && $graph[$u][$v] && $distance[$u] != $INT_MAX && $distance[$u] + $graph[$u][$v] < $distance[$v])
$distance[$v] = $distance[$u] + $graph[$u][$v];
}
PrintResult($distance, $verticesCount);
}
示例:
$graph = array(
array(0, 4, 0, 0, 0, 0, 0, 8, 0),
array(4, 0, 8, 0, 0, 0, 0, 11, 0),
array(0, 8, 0, 7, 0, 4, 0, 0, 2),
array(0, 0, 7, 0, 9, 14, 0, 0, 0),
array(0, 0, 0, 9, 0, 10, 0, 0, 0),
array(0, 0, 4, 0, 10, 0, 2, 0, 0),
array(0, 0, 0, 14, 0, 2, 0, 1, 6),
array(8, 11, 0, 0, 0, 0, 1, 0, 7),
array(0, 0, 2, 0, 0, 0, 6, 7, 0)
);
Dijkstra($graph, 0, 9);
输出
Vertex Distance from source
0 0
1 4
2 12
3 19
4 21
5 11
6 9
7 8
8 14