dijkstra priority queue algorithm (small stack top) of

php achieve Dijkstra algorithm, optimized by small heap top

  1 <?php
  2 
  3 class DEdge
  4 {
  5     public $nextIndex, $length;
  6 
  7     public function __construct($nextIndex, $length)
  8     {
  9         $this->nextIndex = $nextIndex;
 10         $this->length = $length;
 11     }
 12 }
 13 
 14 class DNode
 15 {
 16     public $index, $distance, $edges = [];
 17 
 18     public function __construct($index, $distance)
 19     {
 20         $this->index = $index;
 21         $this->distance = $distance;
 22     }
 23 
 24     public function addEdge(DEdge $edge)
 25     {
 26         $this->edges[] = $edge;
 27     }
 28 }
 29 
 30 class Dijkstra
 31 {
 32     protected $origin;
 33     protected $graph = [], $dGraph = [], $heap = [], $visited = [], $heapVisited = [];
 34 
 35     public function __construct(array $graph, $origin)
 36     {
 37         $this->graph = $graph;
 38         $this->origin = $origin;
 39         $this->visited[$origin] = true;
 40         $this->initializeGraph();
 41         $this->initializeHeap();
 42         $this->calculateDistance();
 43     }
 44 
 45     public function printDistance()
 46     {
 47         foreach ($this->dGraph as $dNodes) {
 48             var_dump([$dNodes->index, $dNodes->distance]);
 49         }
 50     }
 51 
 52     protected function initializeGraph()
 53     {
 54         foreach ($this->graph as $index => $edges) {
 55             $dNode = new DNode($index, $edges[$this->origin]);
 56             foreach ($edges as $toIndex => $edge) {
 57                 $dNode->addEdge(new DEdge($toIndex, $edge));
 58             }
 59             $this->dGraph[$dNode->index] = $dNode;
 60         }
 61     }
 62 
 63     protected function initializeHeap()
 64     {
 65         foreach ($this->dGraph as $index => $node) {
 66             if ($index != $this->origin && $node->distance != INF) {
 67                 $this->addToHeap($node);
 68             }
 69         }
 70     }
 71 
 72     protected function calculateDistance()
 73     {
 74         while (($nearestNode = $this->heapPop()) != null) {
 75             foreach ($nearestNode->edges as $edge) {
 76                 if ($this->dGraph[$edge->nextIndex]->distance >
 77                     $nearestNode->distance + $edge->length) {
 78                     $this->dGraph[$edge->nextIndex]->distance =
 79                         $nearestNode->distance + $edge->length;
 80                     if (!isset($this->heapVisited[$edge->nextIndex])) {
 81                         $this->addToHeap($this->dGraph[$edge->nextIndex]);
 82                     } else {
 83                         $this->keepHeap($this->heapVisited[$edge->nextIndex]);
 84                     }
 85                 }
 86             }
 87         }
 88     }
 89 
 90     protected function heapPop()
 91     {
 92         $heapCount = count($this->heap);
 93         if ($heapCount > 0) {
 94             $this->swap(0, $heapCount - 1);
 95         }
 96         $pop = array_pop($this->heap);
 97         $this->keepHeap(0, false);
 98         return $pop;
 99     }
100 
101     protected function keepHeap($startAt, $up = true)
102     {
103         if ($up) {
104             while ($startAt > 0) {
105                 $parentIndex = intval(($startAt - 1) / 2);
106                 if ($this->heap[$parentIndex]->distance > $this->heap[$startAt]->distance) {
107                     $this->swap($parentIndex, $startAt);
108                     $startAt = $parentIndex;
109                     $this->heapVisited[$this->heap[$startAt]->index] = $startAt;
110                 } else {
111                     break;
112                 }
113             }
114         } else {
115             $lastIndex = count($this->heap) - 1;
116             while ($startAt < $lastIndex) {
117                 $lIndex = 2 * $startAt + 1;
118                 $rIndex = $lIndex + 1;
119                 if (isset($this->heap[$rIndex])) {
120                     $minIndex = $this->heap[$lIndex]->distance <
121                     $this->heap[$rIndex]->distance ? $lIndex : $rIndex;
122                 } else if (isset($this->heap[$lIndex])) {
123                     $minIndex = $lIndex;
124                 } else {
125                     break;
126                 }
127                 if ($this->heap[$startAt]->distance > $this->heap[$minIndex]->distance) {
128                     $this->swap($minIndex, $startAt);
129                     $startAt = $minIndex;
130                     $this->heapVisited[$this->heap[$startAt]->index] = $startAt;
131                 } else {
132                     break;
133                 }
134             }
135         }
136     }
137 
138     protected function addToHeap(DNode $dNode)
139     {
140         $this->heap[] = $dNode;
141         $this->keepHeap(count($this->heap) - 1);
142     }
143 
144     protected function swap($index1, $index2)
145     {
146         list($this->heap[$index1], $this->heap[$index2]) =
147             [$this->heap[$index2], $this->heap[$index1]];
148     }
149 }
150 
151 $graph = [
152     [0, 4, INF, 2, INF],
153     [4, 0, 4, 1, INF],
154     [INF, 4, 0, 1, 3,],
155     [2, 1, 1, 0, 7],
156     [INF, INF, 3, 7, 0],
157 ];
158 
159 $start = 0;
160 
161 $dijkstra = new Dijkstra($graph, $start);
162 
163 $dijkstra->printDistance();

 

Guess you like

Origin www.cnblogs.com/SHQHDMR/p/11184192.html