PHP实现的迪科斯彻(Dijkstra)最短路径算法实例


Posted in PHP onSeptember 16, 2017

本文实例讲述了PHP实现的迪科斯彻(Dijkstra)最短路径算法。分享给大家供大家参考,具体如下:

一、待解决问题

单源最短路径问题,在给定有向图中求一个顶点(单源顶点)到其他所有顶点的最短路径问题。在下图中,每条边上有一个权值,希望求解A到所有其他顶点(B/C/D/E/F/G)的最短路径。

PHP实现的迪科斯彻(Dijkstra)最短路径算法实例

二、问题分析(最短路径的子结构同样最优性)

如果P(A,G)是从顶点A到G的最短路径,假设D和F是这条路径上的中间点,那么P(D,F)一定时从D到F的最短路径。如果P(D,F)不是D到F的最短路径,那必然存在某一个节点M的另一条D到F的路径可以使P(A,B...M...F,G)比P(A,G)小,自相矛盾。

有了这样的性质,我们可以了解Dijkstra算法。

三、Dijkstra算法

Dijkstra 算法,又叫迪科斯彻算法(Dijkstra),又称为单源最短路径算法,所谓单源是在一个有向图中,从一个顶点出发,求该顶点至所有可到达顶点的最短路径问题。 问题描述为设G=(V,E)是一个有向图,V表示顶点,E表示边。它的每一条边(i,j)属于E,都有一个非负权W(I,j),在G中指定一个结点v0,要求把从v0到G的每一个接vj(vj属于V)的最短有向路径找出来(或者指出不存在)。 Dijstra算法是运用贪心的策略,从源点开始,不断地通过相联通的点找出到其他点的最短距离。

Dijkstra的贪心应用在他利用(二)中的性质,不断地选取“最近”的节点并试探每个节点的所有可能存在链接,以起始点为中心向外层层扩展,直到扩展到终点为止。对于源点A,逐步扩展,根据dist[j]=min{dist[j],dist[i]+matrix[i][j]}更新与i直接相邻的顶点信息。

算法描述

1)算法思想:

设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。

2)算法步骤:

a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。

b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。

c.以k为新考虑的中间点,修改U中与k相邻的各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值为顶点k的距离加上k与u边上的权。

d.重复步骤b和c直到所有顶点都包含在S中。

四、算法PHP实现

<?php
class Dijkstra
{
  private $G;
  public function __construct()
  {
    //有向图存储
    $this->G = array(
      array(0,1,2,0,0,0,0),
      array(0,0,0,1,2,0,0),
      array(0,0,0,0,0,2,0),
      array(0,0,0,0,0,1,3),
      array(0,0,0,0,0,0,3),
      array(0,0,0,0,0,0,1),
      array(0,0,0,0,0,0,0),
    );
  }
  public function calculate()
  {
    // 存储已经选择节点和剩余节点
    $U = array(0);
    $V = array(1,2,3,4,5,6);
    // 存储路径上节点距离源点的最小距离
    $d = array();
    //初始化图中节点与源点0的最小距离
    for($i=1;$i<7;$i++)
    {
      if($this->G[0][$i]>0)
      {
        $d[$i] = $this->G[0][$i];
      }
      else
      {
        $d[$i] = 1000000;
      }
    }
    // n-1次循环完成转移节点任务
    for($l=0;$l<6;$l++)
    {
      // 查找剩余节点中距离源点最近的节点v
      $current_min = 100000;
      $current_min_v = 0;
      foreach($V as $k=>$v)
      {
        if($d[$v] < $current_min)
        {
          $current_min = $d[$v];
          $current_min_v = $v;
        }
      }
      //从V中更新顶点到U中
      array_push($U,$current_min_v);
      array_splice($V,array_search($current_min_v,$V),1);
      //更新
      foreach($V as $k=>$u)
      {
        if($this->G[$current_min_v][$u]!=0&&$d[$u]>$d[$current_min_v]+$this->G[$current_min_v][$u])
        {
          $d[$u] = $d[$current_min_v]+$this->G[$current_min_v][$u];
        }
      }
    }
    foreach($d as $k => $u)
    {
      echo $k.'=>'.$u.'<br>';
    }
  }
}
?>

调用类:

$D = new Dijkstra;
$D->calculate();

执行结果:

1=>1
2=>2
3=>2
4=>3
5=>3
6=>4

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
在线短消息收发的程序,不用数据库
Oct 09 PHP
php判断字符以及字符串的包含方法属性
Aug 30 PHP
PHP UTF8编码内的繁简转换类
Jul 20 PHP
php代码运行时间查看类代码分享
Aug 06 PHP
linux下实现定时执行php脚本
Feb 13 PHP
php实现XML和数组的相互转化功能示例
Feb 08 PHP
老生常谈PHP面向对象之命令模式(必看篇)
May 24 PHP
PHP简单实现欧拉函数Euler功能示例
Nov 06 PHP
在Laravel中使用DataTables插件的方法
May 29 PHP
PHPMailer ThinkPHP实现自动发送邮件功能
Jun 10 PHP
详解Laravel5.6 Passport实现Api接口认证
Jul 27 PHP
PHP判断函数是否被定义的方法
Jun 21 PHP
PHP环形链表实现方法示例
Sep 15 #PHP
PHP实现的链式队列结构示例
Sep 15 #PHP
PHP基于堆栈实现的高级计算器功能示例
Sep 15 #PHP
PHP操作MySQL中BLOB字段的方法示例【存储文本与图片】
Sep 15 #PHP
visual studio code 调试php方法(图文详解)
Sep 15 #PHP
PHP简单实现模拟登陆功能示例
Sep 15 #PHP
Thinkphp开发--集成极光推送
Sep 15 #PHP
You might like
谈谈PHP语法(3)
2006/10/09 PHP
如何将数据从文本导入到mysql
2006/10/09 PHP
php5 and xml示例
2006/11/22 PHP
PHP XML error parsing SOAP payload on line 1
2010/06/17 PHP
关于PHP递归算法和应用方法介绍
2013/04/15 PHP
CI框架入门示例之数据库取数据完整实现方法
2014/11/05 PHP
php实现smarty模板无限极分类的方法
2015/12/07 PHP
PHP的Json中文处理解决方案
2016/09/29 PHP
php文件上传类的分享
2017/07/06 PHP
使用XHProf查找PHP性能瓶颈的实例
2017/12/13 PHP
php多进程并发编程防止出现僵尸进程的方法分析
2020/02/28 PHP
php自动加载代码实例详解
2021/02/26 PHP
『jQuery』名称冲突使用noConflict方法解决
2013/04/22 Javascript
jQuery源码解读之addClass()方法分析
2015/02/20 Javascript
JavaScript判断是否为数字的4种方法及效率比较
2015/04/01 Javascript
js判断移动端是否安装某款app的多种方法
2015/12/18 Javascript
JavaScript 判断一个对象{}是否为空对象的简单方法
2016/10/09 Javascript
jQuery+Ajax实现用户名重名实时检测
2017/06/01 jQuery
vue计算属性及使用详解
2018/04/02 Javascript
JS使用遮罩实现点击某区域以外时弹窗的弹出与关闭功能示例
2018/07/31 Javascript
JS实现中英文混合文字溢出友好截取功能
2018/08/06 Javascript
浅析Angular 实现一个repeat指令的方法
2019/07/21 Javascript
微信小程序拖拽排序列表的示例代码
2020/07/08 Javascript
Python选择排序、冒泡排序、合并排序代码实例
2015/04/10 Python
python合并已经存在的sheet数据到新sheet的方法
2018/12/11 Python
详解python播放音频的三种方法
2019/09/23 Python
味多美官网:蛋糕订购,100%使用天然奶油
2017/11/10 全球购物
日本乐天德国站:Rakuten.de
2019/05/16 全球购物
什么是Oracle的后台进程background processes?都有哪些后台进程?
2012/04/26 面试题
委托与事件是什么关系?为什么要使用委托
2014/04/18 面试题
业务员薪酬管理制度
2014/01/15 职场文书
社区活动邀请函范文
2014/01/29 职场文书
python中的None与NULL用法说明
2021/05/25 Python
一起来学习Python的元组和列表
2022/03/13 Python
《极主夫道》真人电影正式预告 定档6月3日上映
2022/04/05 日漫
Python+OpenCV实现图片中的圆形检测
2022/04/07 Python