<?php
/**
*
* @param int $start_id 起点节点id
* @param int $end_id 终点节点id
* @param array $node_arr 所有节点信息数据
* @author
* 迪杰斯特拉 单源最短路劲计算
*
*/
function dijkstar($start_id, $end_id, $node_arr)
{
$start_node_id = $start_id;//设置开始节点
//点位数据格式处理
foreach ($node_arr as $node_info) {
foreach ($node_info['next_node'] as $key => $next_node) {
$i_cost[$node_info['node_id']][$next_node]['distance'] = $node_info['distance'][$key];
}
$i_dist[$node_info['node_id']]['distance'] = 'INF'; // 初始化为无穷大
$i_dist[$node_info['node_id']]['road'] = $start_node_id; // 初始化为起点
$b_mark[$node_info['node_id']] = false; // 初始化未加入
}
/*var_dump($i_cost);
var_dump($i_dist);
var_dump($b_mark);*/
$i_dist[$start_node_id]['distance'] = 0; // 初始点到其本身的距离为0
$b_mark[$start_node_id] = true; // 初始点加入集合
$current_node_id = $start_node_id; // 最近加入的节点id
$node_count = count($node_arr);//需要循环的次数
/*var_dump($i_dist);
var_dump($b_mark);
var_dump($node_count);*/
for ($i = 0; $i < $node_count; $i++) {
$min = 'INF';
// 当前节点的最近距离
if (isset($i_cost[$current_node_id])&&is_array($i_cost[$current_node_id])) {
foreach ($i_cost[$current_node_id] as $key => $val) {
if ($i_dist[$key]['distance'] == 'INF' || $i_dist[$key]['distance'] > $i_dist[$current_node_id]['distance'] + $val['distance']) {
$i_dist[$key]['distance'] = $i_dist[$current_node_id]['distance'] + $val['distance'];
$i_dist[$key]['road'] = $i_dist[$current_node_id]['road'] . '#' . $key;
}
}
}
foreach ($i_dist as $key => $val) {
if (!$b_mark[$key]) {
if ($val['distance'] != 'INF' && ($min == 'INF' || $min > $val['distance'])) {
$min = $val['distance'];
$candidate_node_id = $key; // 候选最近结点id
}
}
}
if ($min == 'INF') {
break;
}
$current_node_id = $candidate_node_id;
$b_mark[$current_node_id] = true;
}
/*foreach ($i_dist as $key => $val) {
echo $start_node_id . '=>' . $key . ':' . $val['distance'] . '<br />';
}*/
//获取最短路径
$arr = $i_dist[$end_id]['road'];
echo '最短路径:'.str_replace('#','=>',$arr);
echo '<br />';
echo '距离为:'.$i_dist[$end_id]['distance'];
var_dump($i_dist);
}
//所有节点信息
$node_arr = [
[
'node_id' => 1,//当前节点id
'next_node' => [
2,
4,
],//可通往的节点
'distance' => [
10,
5,
],//相对应的节点距离
],
[
'node_id' => 2,
'next_node' => [
1,
5
],
'distance' => [
10,
5
],
],
[
'node_id' => 3,
'next_node' => [
6
],
'distance' => [
5
],
],
[
'node_id' => 4,
'next_node' => [
1,
6,
7,
8,
5,
11
],
'distance' => [
5,
15,
5,
8,
10,
5
],
],
[
'node_id' => 5,
'next_node' => [
2,
4,
8,
7,
6,
12
],
'distance' => [
5,
10,
8,
5,
15,
5
],
],
[
'node_id' => 6,
'next_node' => [
3,
4,
5,
7,
8
],
'distance' => [
5,
15,
15,
11,
11
],
],
[
'node_id' => 7,
'next_node' => [
4,
8,
5,
6,
9
],
'distance' => [
5,
3,
8,
11,
5
],
],
[
'node_id' => 8,
'next_node' => [
5,
7,
4,
6
],
'distance' => [
5,
3,
8,
11
],
],
[
'node_id' => 9,
'next_node' => [
10,
11,
12
],
'distance' => [
3,
15,
18
],
],
[
'node_id' => 10,
'next_node' => [
8,
9,
11,
12
],
'distance' => [
5,
3,
18,
15
],
],
[
'node_id' => 11,
'next_node' => [
12,
4,
9,
10
],
'distance' => [
10,
5,
15,
18
],
],
[
'node_id' => 12,
'next_node' => [
11,
10,
9,
5
],
'distance' => [
10,
15,
18,
5
],
],
];
dijkstar(2, 8, $node_arr);
?>