优先级队列(小顶堆)的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();

原文地址:https://www.cnblogs.com/SHQHDMR/p/11184192.html

时间: 2024-07-29 05:34:51

优先级队列(小顶堆)的dijkstra算法的相关文章

配对堆优化Dijkstra算法小记

关于配对堆的一些小姿势: 1.配对堆是一颗多叉树. 2.包含优先队列的所有功能,可用于优化Dijkstra算法. 3.属于可并堆,因此对于集合合并维护最值的问题很实用. 4.速度快于一般的堆结构(左偏树,斜堆,随机堆--),具体时间复杂度: 合并(Merge):$O(1)$: 插入(Insert/Push):$O(1)$: 修改值(Change):$O(1) \sim O(\log n)$: 取出维护的最值(Top):$O(1)$: 弹出堆顶元素(Pop):$O(\log n)$: 我们依然拿洛

POJ3253 Fence Repair 小顶堆+贪心

给了你N个木棒,求把他们组装成一根需要的最小花费,每次只能选两根组装在一起,需要的花费为两个木棒之和, 以前遇到过把一整根切开的,那个是DP,这个则有些类似,可是大胆的猜测了一下,直接每次选取所有木棒中最短的两根,这样就可以了,那么贪心是适用的,但是数量很多,而且两根最短的组装好了得插回去,这样不可能每次都排序吧, 这题首先优先队列肯定是可以做的, 最小堆也是可以的,每次都选出堆里的最小的两个求和再放回去即可 队列本身也就是堆吧,所以差别不大,但是没用过最小堆最大堆的 所以用一次把 #inclu

wikioi 2573 大顶堆与小顶堆并用

题目描述 Description 我们使用黑匣子的一个简单模型.它能存放一个整数序列和一个特别的变量i.在初始时刻,黑匣子为空且i等于0.这个黑匣子能执行一系列的命令.有两类命令: ADD(x):把元素x放入黑匣子:GET:把i加1的同时,输出黑匣子内所有整数中第i小的数.牢记第i小的数是当黑匣子中的元素已非降序排序后位于第i位的元素. 下面的表6_4是一个11个命令的例子: 表6_4 编号 命令 i 黑匣子内容 输出 1 ADD(3) 0 3 2 GET 1 3 3 3 ADD(1) 1 1,

wikioi 1245 小顶堆

题目描述 Description 有两个长度为 N 的序列 A 和 B,在 A 和 B 中各任取一个数可以得到 N^2 个和,求这N^2 个和中最小的 N个. 输入描述 Input Description 第一行输入一个正整数N:第二行N个整数Ai 且Ai≤10^9:第三行N个整数Bi, 且Bi≤10^9 输出描述 Output Description 输出仅一行,包含 n 个整数,从小到大输出这 N个最小的和,相邻数字之间用 空格隔开. 样例输入 Sample Input 5 1 3 2 4

heap c++ 操作 大顶堆、小顶堆

在C++中,虽然堆不像 vector, set 之类的有已经实现的数据结构,但是在 algorithm.h 中实现了一些相关的模板函数.下面是一些示例应用 http://www.cplusplus.com/reference/algorithm/pop_heap/ #include <iostream> #include <algorithm> // make_heap(), pop_heap(), push_heap() #include <vector> using

python 大顶堆 小顶堆

http://www.coder4.com/archives/3844 需1求:给出N长的序列,求出TopK大的元素,使用小顶堆,heapq模块实现. import heapq import random class TopkHeap(object): def __init__(self, k): self.k = k self.data = [] def Push(self, elem): if len(self.data) < self.k: heapq.heappush(self.data

BZoj 1293 生日礼物(小顶堆)

传送门:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27400 Anayse:小顶堆: 1 1 5     - >    1 3 5     ->    3 5 7    ->     5 7 8 pop(1)    p(1)      p(3)       最优解. 每次剔除堆顶,然后换push与堆顶相同种类的珠子,由于单调,,距离会被缩短,于是找出最优解.详见上式. push()  log(n) so,复杂度

剑指offer:数据流中的中位数(小顶堆+大顶堆)

1. 题目描述 /** 如何得到一个数据流中的中位数? 如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值. 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值. 我们使用 Insert()方法读取数据流,使用 GetMedian()方法获取当前读取数据的中位数. */ 2. 思路 /** 最大堆和最小堆 * 每次插入小顶堆的是当前大顶堆中最大的数 * 每次插入大顶堆的是当前小顶堆中最小的数 * 这样保证小顶堆中的数永远大于等于大顶堆中的数(值

7-31 笛卡尔树 (25分)--判断二叉搜索树,小顶堆

先初步判断是否满足二叉搜索树和小顶堆(针对每一颗最小的子树),如果都满足,进一步判断整棵树是否满足. 1 #include <iostream> 2 #include <string> 3 #include <cstring> 4 using namespace std; 5 typedef struct node 6 { 7 int K1; 8 int K2; 9 int L; 10 int R; 11 }node_arr[1001]; 12 node_arr s;