-
Notifications
You must be signed in to change notification settings - Fork 0
/
Dijkstra.php
109 lines (75 loc) · 1.96 KB
/
Dijkstra.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<?php
/*
* Author: doug@neverfear.org
*/
require_once("PriorityQueue.php");
class Edge {
public $start;
public $end;
public $weight;
public function __construct($start, $end, $weight) {
$this->start = $start;
$this->end = $end;
$this->weight = $weight;
}
}
class Graph {
public $nodes = array();
public function addedge($start, $end, $weight = 0) {
if (!isset($this->nodes[$start])) {
$this->nodes[$start] = array();
}
array_push($this->nodes[$start], new Edge($start, $end, $weight));
}
public function removenode($index) {
array_splice($this->nodes, $index, 1);
}
public function paths_from($from) {
$dist = array();
$dist[$from] = 0;
$visited = array();
$previous = array();
$queue = array();
$Q = new PriorityQueue("compareWeights");
$Q->add(array($dist[$from], $from));
$nodes = $this->nodes;
while($Q->size() > 0) {
list($distance, $u) = $Q->remove();
if (isset($visited[$u])) {
continue;
}
$visited[$u] = True;
foreach($nodes[$u] as $edge) {
$alt = $dist[$u] + $edge->weight;
$end = $edge->end;
if (!isset($dist[$end]) || $alt < $dist[$end]) {
$previous[$end] = $u;
$dist[$end] = $alt;
$Q->add(array($dist[$end], $end));
}
}
}
return array($dist, $previous);
}
public function paths_to($node_dsts, $tonode) {
// unwind the previous nodes for the specific destination node
$current = $tonode;
$path = array();
if (isset($node_dsts[$current])) { // only add if there is a path to node
array_push($path, $tonode);
}
while(isset($node_dsts[$current])) {
$nextnode = $node_dsts[$current];
array_push($path, $nextnode);
$current = $nextnode;
}
return array_reverse($path);
}
public function getpath($from, $to) {
list($distances, $prev) = $this->paths_from($from);
return $this->paths_to($prev, $to);
}
}
function compareWeights($a, $b) {
return $a->data[0] - $b->data[0];
}