迪杰斯特拉算法(PHP实现)

本文介绍了如何使用PHP实现迪杰斯特拉算法,详细解释了算法思路,并提供了一个具体的代码示例。通过该算法,可以找出图中从指定源点到其他所有顶点的最短路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<?php
/**
 *带权有向图dijkstra(迪杰斯特拉)算法
 * 时间复杂度O(n^3)
 * 思路:
 * 1 将图的顶点分成两部分,S(最短路径顶点集),U(除了S集以外的顶点集)
 * 2 v到S中顶点距离小于v到U中任意顶点距离
 * 3 v到U中顶点的最小距离,那么该路径必定过S中顶点
 * 步骤:
 * 1 初始时,S只包含源点,S={v},v的距离为0.U包含除v以外的其他顶点,即U={其余顶点},若v与U中顶点u有边,则<u,v>有权值,不是临接点权值为无穷。
 * 2 从U中选取一个距离v最小的顶点k,加入S中(距离为v到k的最短距离)。
 * 3 以k为中间点,从源点到u点的距离m(经过中间点k),nm(不经过中间点k),如果m<nm,那么需要修改u点的权(经过中间点边的权之和),并将u加入S中。
 * 4 重复2,3步骤直到所有的顶点都包含在S中。
 * 最终要的思想:
 *  通过边来松弛v到其他顶点的路程
 */
class Dijkstra{
    const MAXINT = 32767;
    const MAXNUM = 6;
    private $v;
    public static $dist;
    public function __construct($v)
    {
        $this->v = $v;
        self::$dist = [];
    }

    //该矩阵表示图之间顶点的连接关系及权值
    private static $map = [
        [0,self::MAXINT,10,self::MAXINT,30,100],
        [self::MAXINT,0,5,self::MAXINT,self::MAXINT,self::MAXINT],
        [self::MAXINT,self::MAXINT,0,50,self::MAXINT,self::MAXINT],
        [self::MAXINT,self::MAXINT,self::MAXINT,0,self::MAXINT,10],
        [self::MAXINT,self::MAXINT,self::MAXINT,20,0,60],
        [self::MAXINT,self::MAXINT,self::MAXINT,self::MAXINT,self::MAXINT,0]
    ];

    public function Dijkstra(){
        if($this->v >= self::MAXNUM){
            throw new \Exception("图的最大阶".self::MAXNUM."顶点的下标范围:0~".(self::MAXNUM-1));
        }

        $n = self::MAXNUM;
        $s = [];
        //S集合点数组初始化
        for($i = 0; $i<$n; $i++){
            $s[$i] = false;
            //初始化v0到其他点的距离(理论)
            self::$dist[$i] = self::$map[$this->v][$i];
        }

        self::$dist[$this->v] = 0;//该点到自己距离初始化0
        $s[$this->v] = true;//将点v0初始化到S中

        for($i =0; $i<$n; $i++){
            $mindist = self::MAXINT;
            //找到离v最近的顶点$u
            for($j=0; $j<$n; $j++){
                if(empty($s[$j]) && self::$dist[$j] < $mindist){
                    $mindist = self::$dist[$j];
                    $u = $j;
                }
            }
            $s[$u] = true;
            //更新其他点以S中点为中间点的最短距离
            for ($v=0; $v<$n; $v++){
                if(self::$map[$u][$v] < self::MAXINT && self::$map[$u][$v] + self::$dist[$u] < self::$dist[$v]){
                    //最短路径递增
                    self::$dist[$v] = self::$dist[$u] + self::$map[$u][$v];
                }
            }
        }
    }
}

$dj = new Dijkstra(0);
$dj -> Dijkstra();
print_r(Dijkstra::$dist);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值