优先级队列(小顶堆)的dijkstra算法

Posted shqhdmr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了优先级队列(小顶堆)的dijkstra算法相关的知识,希望对你有一定的参考价值。

php实现迪杰斯特拉算法,并由小顶堆优化

  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();

 

以上是关于优先级队列(小顶堆)的dijkstra算法的主要内容,如果未能解决你的问题,请参考以下文章

《漫画算法》源码整理-4 大顶堆 小顶堆 优先队列

优先级队列及小顶堆排序

Java优先队列一些问题

[剑指offer] 41. 数据流中的中位数 (大小堆,优先队列)

用大顶堆实现优先队列

优先级队列的总结