所有分类
  • 所有分类
  • 后端开发
PHP 中图算法的应用:Dijkstra 算法与 Kruskal 算法

PHP 中图算法的应用:Dijkstra 算法与 Kruskal 算法

算法:查找无权重图中从源节点到所有其他节点的最短路径。算法:构建指定权重的图中的最小生成树。中实现图算法图算法是处理由节点和边组成的数据结构的强大工具。中,可以使用不同的算法来解决各种图相关问题。算法可用于构建具有指定权重的图中的最小生成树

搞定PHP里的图数据结构有点儿难,但是咱们有个法宝——厉害的图算法!这个文章就要教你怎么用PHP玩转Dijkstra和Kruskal算法,这俩家伙可是图形问题的杀手锏。

Dijkstra算法的基本概念

Dijkstra算法简单说就是帮你找到最佳路线,不管有没有权重。它的这个过程就像是一棵不断长高的大树,每一步都会选择最矮的那根树枝来突破。最关键的地方就在于,它每次都选最短的路走,这样才能从起点连到终点。

搞定Dijkstra算法可离不开一个老伙计——优先队列。这个东西,在PHP里咱就用数组来代替。啥步骤?首先,把所有节点的距离设成宇宙最大值,差点儿忘了那源头,它得是零!然后不停地循环直到每个节点都干掉:找出队列里距离最短的那家伙,让它身边的小伙伴们知道新情况(更新它们的距离),接着让这些知情人入团(放入队列)。

Dijkstra算法的PHP实现

要搞定PHP中的Dijkstra算法,我们得掌握一些基础的图形知识,比如如何表示图以及如何用优先队列搞事情。你可能会觉得邻接矩阵或者邻接表这两个东东比较难理解,但是没关系,我们只需要敲几行代码就能把这个算法的原理弄明白了。看下面这个PHP的小例子就是这么简单的一回事儿~

php
PHP 中图算法的应用:Dijkstra 算法与 Kruskal 算法
搞定这个dijkstra(伊姆斯特)算法,只需要给你的矩阵$graph'和起点变量$source就行了!
    $dist = [];
    $visited = [];
    $nodes = count($graph);
从0开始数,数到所有节点,每次加1。
        $dist[$i] = PHP_INT_MAX;
        $visited[$i] = false;
    }
    $dist[$source] = 0;
从零开始,每加上一次$count,就检查下$count是不是小于剩余的节点数。
对的,就是取最小距离。$u=$dist和$visited两个数值中的较小者!
        $visited[$u] = true;
只要$v还没到$nodes,就自加1去循环。
如果没碰到过$v,而且在$graph文件里也能找到$u和$v的相连关系,然后$dist[$u]还不是PHP最大值的话,最重要的是$dist[$u]+$graph[$u][$v]要比$dist[$v]小才行。
距离等于起点到终点的长度加上中间那个点的尺寸。
            }
        }
    return $dist;
}
在这里,我们来聊聊怎么求 ̶d²$。首先得知道你现在走过的路(即$ visited$)和已经去过的地方(即 $dist$)。然后?还需要一个小工具:优化过的公式。这个公式就是让我们把每一步都算出来,加起来就得到了最后的答案——距离最小值。
    $min = PHP_INT_MAX;
    $minIndex = -1;
遍历一下每一个距离,并取名为$node和$distance。
如果没去过那个节点,而且距离小于等于某个值?
            $min = $distance;
            $minIndex = $node;
    return $minIndex;

Kruskal算法的基本概念

Kruskal算法就是用来找出有特定权值的图形里最小的生成树。这个最小的生成树包含了图形所有节点,而且每条边的重量加起来是最均匀的。Kruskal算法的步骤很简单,就是在图形里找出最小的线,然后保证不会出现圈再连起来,这样就可以逐渐地找到整个的最小生成树。

Kruskal算法就是挑边和找圈滴事儿。在咱们PHP里头,用那个叫”并查集”的东西就能快速帮你找出圈子了。这个并查集就是一个把各种元素分门别类的好工具,它能让你方便快捷地找到合适的对象,还能进行即时合并!

Kruskal算法的PHP实现

搞定Kruskal算法得懂点数据库的门道,特别是怎样用数组(或链表)创建交集(即所谓的“并查集”)。就是这么回事儿,一边敲敲代码,一边琢磨这个算法怎么运作就行了。

function kruskal($graph) {

class Graph {
    private $nodes = [];
    private $edges = [];
    public function addNode($node) {
        $this->nodes[] = $node;
    }
    public function addEdge($node1, $node2, $weight = 1) {
        $this->edges[$node1][$node2] = $weight;
    }
    public function dijkstra($source) {
        $distances = array_fill_keys($this->nodes, INF);
        $distances[$source] = 0;
        $visited = [];
        while (count($visited) nodes)) {
            $minDistance = INF;
            $minDistanceNode = null;
            foreach ($this->nodes as $node) {
                if (!in_array($node, $visited) && $distances[$node] edges[$minDistanceNode] as $neighbor => $weight) {
                $newDistance = $distances[$minDistanceNode] + $weight;
                if ($newDistance addNode('A');
$graph->addNode('B');
$graph->addNode('C');
$graph->addNode('D');
$graph->addEdge('A', 'B', 6);
$graph->addEdge('A', 'C', 8);
$graph->addEdge('A', 'D', 10);
$graph->addEdge('B', 'C', 3);
$graph->addEdge('B', 'D', 9);
$graph->addEdge('C', 'D', 12);
$distances = $graph->dijkstra('A');
var_dump($distances);

$result = [];

$i = 0;

$e = 0;

$graph = sortEdges($graph);

$parent = [];

$rank = [];

循环遍历每个节点,检查它们的边。

$parent[$node] = $node;

$rank[$node] = 0;

while $e < parent total minus one.

我们这样来分析,先取$graph[]数组中的第$i$个元素,然后用它依次给$u、$v、$w赋值。

$i++;

$x = find($parent, $u);

$y = find($parent, $v);

if ($x != $y) {

$e++;

$result[] = [$u, $v, $w];

就是把$parent和$rank加起来,再加上$x和$y。

return $result;

function find($parent, $i) {

if ($parent[$i] != $i) {

把$parent里的第$i个元素的位置,放到变量$parent里。

return $parent[$i];

咱们来做个union函数,参数有$parent(父节点)、$rank(层级编号)和$x,$y(坐标值)。

$xroot = find($parent, $x);

$yroot = find($parent, $y);

如果$rank[$xroot]$比$rank[$yroot]$小,那就这样。

$parent[$xroot] = $yroot;

class Graph {
    private $nodes = [];
    private $edges = [];
    public function addNode($node) {
        $this->nodes[] = $node;
    }
    public function addEdge($node1, $node2, $weight = 1) {
        $this->edges[] = [$node1, $node2, $weight];
    }
    public function kruskal() {
        $parents = array_fill_keys($this->nodes, null);
        $ranks = array_fill_keys($this->nodes, 0);
        usort($this->edges, function($a, $b) {
            return $a[2] - $b[2];
        });
        $mst = [];
        foreach ($this->edges as $edge) {
            $x = $this->find($edge[0], $parents);
            $y = $this->find($edge[1], $parents);
            if ($x != $y) {
                $mst[] = $edge;
                $this->union($x, $y, $parents, $ranks);
            }
        }
        return $mst;
    }
    private function find($node, &$parents) {
        if ($parents[$node] === null) {
            return $node;
        }
        return $this->find($parents[$node], $parents);
    }
    private function union($x, $y, &$parents, &$ranks) {
        $xRoot = $this->find($x, $parents);
        $yRoot = $this->find($y, $parents);
        if ($xRoot == $yRoot) {
            return;
        }
        if ($ranks[$xRoot] > $ranks[$yRoot]) {
            $parents[$yRoot] = $xRoot;
        } else if ($ranks[$xRoot] addNode('A');
$graph->addNode('B');
$graph->addNode('C');
$graph->addNode('D');
$graph->addEdge('A', 'B', 6);
$graph->addEdge('A', 'C', 8);
$graph->addEdge('A', 'D', 10);
$graph->addEdge('B', 'C', 3);
$graph->addEdge('B', 'D', 9);
$graph->addEdge('C', 'D', 12);
$mst = $graph->kruskal();
var_dump($mst);

除了$Rank[$xroot]>=$Rank[$yroot]$之外,如果还满足下面这个条件,那就…

$parent[$yroot] = $xroot;

} else {

$rank[$xroot]++;

图算法的实际应用

说白了,图算法就是好用!特别在网络传输,社交网络啥的都能派上用场。比如你在解决图问题时,就有如Dijkstra和Kruskal这样的厉害助手。它们能帮你找出用户间最短路径或最小生成树。这个可对于了解网络动态,真是超乎想象的管用!

图算法的优化技巧

实际用起来,图算法有时候会卡住。想让它跑得快点儿,咱可以搞点小手段!比如,给这个Dijkstra算法弄点儿二叉堆或者斐波那契堆加速处理优先级排序。再说了,那个啥Kruskal算法也能用上路径压缩和按照顺序合并来搞定并查集的速度。

图算法的未来发展

现在的大数据和人工智能进步得很快,对图算法运用的前景越来越好!比如推荐系统、知识图谱和复杂网络分析这些地方,都能期待到图算法继续发挥大作用。所以只要科学家们不断努力,弄出更厉害的新算法,就肯定能搞定复杂的图数据结构了。

老铁们记住,PHP里的图算法能帮咱们轻松驾驭图数据结构!花时间学习并练熟Dijkstra和Kruskal计算法,遇到什么实际难题都不怕,还能让咱的应用更给力!下面我问大家一个问题哈:你们觉得将来图算法能干啥大事儿?会面临啥新挑战不?赶紧到留言区聊聊呗,也别忘了点个赞和转发这篇文章,让更多的小伙伴都能用上这个厉害的图算法呦~

原文链接:https://www.icz.com/technicalinformation/web/2024/07/19881.html,转载请注明出处~~~
0

评论0

请先
注意:请收藏好网址www.icz.com,防止失联!站内免费资源持续上传中…!赞助我们
显示验证码
没有账号?注册  忘记密码?