/**
  * {@inheritdoc}
  */
 public function calculate($start, $finish)
 {
     // check if the nodes exist
     if (!isset($this->nodes[$start])) {
         throw new \InvalidArgumentException("The starting node '" . $start . "' is not found");
     }
     if (!isset($this->nodes[$finish])) {
         throw new \InvalidArgumentException("The ending node '" . $finish . "' is not found");
     }
     $distances = [];
     $distances[$start] = 0;
     $visited = [];
     $previous = [];
     $queue = new PriorityQueue();
     $queue->insert($start, $distances[$start]);
     $queue->top();
     while ($queue->valid()) {
         $smallest = $queue->current();
         if ($smallest == $finish) {
             // trying to make path
             $path = array();
             while (isset($previous[$smallest])) {
                 $path[] = $smallest;
                 $smallest = $previous[$smallest];
             }
             $path[] = $start;
             return ['distance' => $distances[$finish], 'path' => array_reverse($path)];
         }
         if (isset($visited[$smallest])) {
             $queue->next();
             continue;
         }
         $visited[$smallest] = true;
         foreach ($this->nodes[$smallest] as $neighbor => $weight) {
             if (isset($visited[$neighbor])) {
                 continue;
             }
             $alt = $distances[$smallest] + $weight;
             if (!isset($distances[$neighbor]) || $alt < $distances[$neighbor]) {
                 $distances[$neighbor] = $alt;
                 $previous[$neighbor] = $smallest;
                 $queue->insert($neighbor, $alt);
             }
         }
         $queue->next();
     }
     // there is no available path if the graph is unconnected
     return null;
 }
Ejemplo n.º 2
0
 public function shortest_path($start, $finish)
 {
     $distances = array();
     $previous = array();
     $nodes = new PriorityQueue();
     foreach ($this->verticies as $vertex => $value) {
         if ($vertex === $start) {
             $distances[$vertex] = 0;
             $nodes->insert($vertex, 0);
         } else {
             $distances[$vertex] = PHP_INT_MAX;
             $nodes->insert($vertex, PHP_INT_MAX);
         }
         $previous[$vertex] = null;
     }
     $nodes->top();
     while ($nodes->valid()) {
         $smallest = $nodes->current();
         if ($smallest === $finish) {
             $path = array();
             while ($previous[$smallest]) {
                 $path[] = $smallest;
                 $smallest = $previous[$smallest];
             }
             $path[] = $start;
             $alt = $distances[$finish];
             $path['Разстояние'] = $alt;
             return array_reverse($path);
         }
         if ($smallest === null || $distances[$smallest] === PHP_INT_MAX) {
             break;
         }
         foreach ($this->verticies[$smallest] as $neighbor => $value) {
             $alt = $distances[$smallest] + $this->verticies[$smallest][$neighbor];
             if ($alt < $distances[$neighbor]) {
                 $distances[$neighbor] = $alt;
                 $previous[$neighbor] = $smallest;
                 $nodes->insert($neighbor, $alt);
             }
         }
         $nodes->next();
     }
     return $distances;
 }