迪克斯特拉(Dijkstra)算法php 实现

<?php
class Graph{

    private $data = [];
    const INFINITY = -1;

    public function addDirection( $fromNode, $toNode,$cost ){
        if( !isset($this->data[$fromNode]) ){
            $this->data[$fromNode] = [];
        }
        $this->data[$fromNode][$toNode] = $cost;
    }

    public function getNeighters( $node ){
        return $this->data[$node] ?? [];
    }

    public function printData(){
        print_r( $this->data );
    }

}

class DK{

    public $graph = null;
    private $costs = [];
    private $parents = [];
    public $processedNodes = [];

    public function getGraph() : Graph{
        if( $this->graph == null ){
            $this->graph = new Graph();
        }
        return $this->graph;
    }

    public function printGraph(){
        return $this->getGraph()->printData();
    }

    public function addDirection($fromNode,$toNode,$cost){
        $this->getGraph()->addDirection( $fromNode,$toNode,$cost );
    }

    public function getCosts( $fromNode, $toNode ){
        $this->initCosts( $fromNode, $toNode );
        $node = $this->getLowestNode();
        while ( $node ){
            $cost = $this->getCost( $node );
            foreach ( $this->getGraph()->getNeighters($node) as $neighterNode => $neighterCost ){
                $newCost = $cost + $neighterCost;
                if( $this->costs[$neighterNode] == Graph::INFINITY || !isset($this->costs[$neighterNode]) || $newCost < $cost ){
                    $this->costs[$neighterNode] = $newCost;
                    $this->parents[$neighterNode] = $node;
                }
            }
            array_push($this->processedNodes, $node);
            $node = $this->getLowestNode();
        }
        return $this->costs;
    }

    public function initCosts($fromNode, $toNode){
        $nodes = $this->getGraph()->getNeighters($fromNode);
        foreach ($nodes as $_node => $cost ){
            $this->costs[$_node] = $cost;
        }
        if( !isset( $this->costs[$toNode] ) ){
            $this->costs[$toNode] = Graph::INFINITY;
        }
    }

    public function getCost( $toNode ){
        return $this->costs[$toNode] ?? Graph::INFINITY;
    }

    private function getLowestNode(){
        $lowestNode = null;
        $lowestCost = Graph::INFINITY;
        foreach ( $this->costs as $node =>$cost ){
            if( $cost == Graph::INFINITY || in_array($node, $this->processedNodes) ){
                continue;
            }

            if( $lowestCost == Graph::INFINITY || $cost < $lowestCost ){
                $lowestCost = $cost;
                $lowestNode = $node;
            }
        }
        return $lowestNode;
    }
}

$dk = new DK();
$dk->addDirection('shenyang','liaoyang', 5 );
$dk->addDirection('shenyang', 'anshan', 1);
$dk->addDirection('anshan','dalian',5);
$dk->addDirection('liaoyang','dalian', 2 );
$dk->addDirection('dalian','panjin', 7 );

$dk->printGraph();

var_dump($dk->getCosts('shenyang','panjin'));
?>

  

posted @ 2020-08-31 16:34  ﹏Sakura  阅读(358)  评论(0编辑  收藏  举报