php地铁,php使用Dijkstra 算法求得地铁/公交最短路线

1.核心文件(service)

namespace app\Http\Services;

class Dijkstra2Service

{

protected $graph=[];//只需要存每个节点所对应的邻居们,就能表示一个图了

protected $parents=[];//保存父级关系,最终能通过这个数组,回溯走过的最短路线

protected $costs;//从起点,到每个节点的花销

protected $infinity=999999;//用一个很大的数字,来代表一个正无穷大

protected $processed=[];//已处理过的节点的key

protected $start;

protected $end;

public function __construct($graph,$start,$end)

{

$this->graph=$graph;

$this->start=$start;

$this->end=$end;

//初始化父级数组, 即:只知道start的邻居,就是start的父级

foreach ($this->graph[$this->start] as $k=>$v) {

$this->parents[$k]=$this->start;

}

//初始化花销数组,即:只知道start的邻居节点的花销,其它节点都是正无穷

foreach ($this->graph as $k=>$v) {

if($k==$this->start){

$this->costs=$this->graph[$this->start];

}elseif(empty($this->costs[$k])){

$this->costs[$k]=$this->infinity;

}

}

$this->costs[$end]=$this->infinity;

}

public function find(){

$nodeKey=$this->findLowestCostNode($this->costs);

while ($nodeKey){//只要还有未处理过的节点

$cost=$this->costs[$nodeKey];

$neighbors=$this->graph[$nodeKey] ?? [];//取邻居

//遍历邻居

foreach ($neighbors as $k=> $v) {

$newCost=$cost+$v;

if(isset($this->costs[$k]) && $this->costs[$k] > $newCost){

$this->costs[$k]=$newCost;//将更低的开销更新

$this->parents[$k]=$nodeKey;

}

}

//既然已处理完了该节点的所有邻居,那么将该节点标记为已处理过了

$this->processed[]=$nodeKey;

//找出下一个待处理的节点

$nodeKey=$this->findLowestCostNode();

}

return $this->showResult();

}

//在未处理过的节点中,查找出最短的那个

protected function findLowestCostNode(){

$lowestCost=$this->infinity;//在这里设置为正无穷是为了,在第一次进入循环时,必然比第一个元素大

$lowestCostKey=false;//要返回的最短路径节点的key

foreach ($this->costs as $k=>$v) {

if($vprocessed)){

$lowestCost=$v;

$lowestCostKey=$k;

}

}

return $lowestCostKey;

}

//美化显示处理结果

protected function showResult(){

$path=[];

$key=$this->end;

//从终点开始,查找父级,回溯出最短路线

while (isset($this->parents[$key])){

array_unshift($path,$key);

$key=$this->parents[$key];

}

$data=['count'=>'最短路径全长是:' . $this->costs[$this->end],'path'=>'路线是:'.$this->start.'->' . implode('->',$path)];

return $data;

}

}

2.控制器使用

namespace app\Http\Controllers\Api\Mini;

use App\Http\Services\Dijkstra2Service;

class TestController

{

public function testFindWeight()

{

$start="太白南路";

$end="新政中心";

$graph=[

"太白南路"=>[

"科技路"=>1,

"小寨"=>2,

],

"科技路"=>[

"西北工业大学"=>1,

"太白南路"=>1,

],

"西北工业大学"=>[

"科技路"=>1,

"南稍门"=>3,

],

"小寨"=>[

"南稍门"=>2,

"太白南路"=>2,

"大雁塔"=>1,

],

"南稍门"=>[

"小寨"=>2,

"西北工业大学"=>3,

"建筑科技大学"=>2,

"新政中心"=>10,

],

"建筑科技大学"=>[

"南稍门"=>2,

"新政中心"=>1,

],

];

//$graph正常从数据库读取,新数据拼接而成

$obj=new Dijkstra2Service($graph,$start,$end);

$data=$obj->find();

return $data;

}

}

3.最终结果

{

"count": "最短路径全长是:7",

"path": "路线是:太白南路->小寨->南稍门->建筑科技大学->新政中心"

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值