Skip to content

Commit ace6c44

Browse files
committed
add Dijkstra SP
1 parent ede14b1 commit ace6c44

File tree

7 files changed

+141
-15
lines changed

7 files changed

+141
-15
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ To test each algorithm(data structure), instead of running the file directly, yo
7474
* [KruskalMST](kruskal_mst.go)
7575
* Shortest Paths
7676
* [EdgeWeightedDigraph](edge_weighted_digraph.go)
77+
* [DijkstraSP](dijkstra_sp.go)
7778

7879
* 5 STRING
7980

cmd/dijkstra-sp/main.go

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/******************************************************************************
2+
* Execution: go run cmd/dijkstra-sp/main.go input.txt s
3+
* Data files: https://algs4.cs.princeton.edu/44sp/tinyEWD.txt
4+
* https://algs4.cs.princeton.edu/44sp/mediumEWD.txt
5+
* https://algs4.cs.princeton.edu/44sp/largeEWD.txt
6+
*
7+
* Dijkstra's algorithm. Computes the shortest path tree.
8+
* Assumes all weights are nonnegative.
9+
*
10+
* % go run cmd/dijkstra-sp/main.go tinyEWD.txt 0
11+
* 0 to 0 (0.00)
12+
* 0 to 1 (1.05) 0->4 0.38 4->5 0.35 5->1 0.32
13+
* 0 to 2 (0.26) 0->2 0.26
14+
* 0 to 3 (0.99) 0->2 0.26 2->7 0.34 7->3 0.39
15+
* 0 to 4 (0.38) 0->4 0.38
16+
* 0 to 5 (0.73) 0->4 0.38 4->5 0.35
17+
* 0 to 6 (1.51) 0->2 0.26 2->7 0.34 7->3 0.39 3->6 0.52
18+
* 0 to 7 (0.60) 0->2 0.26 2->7 0.34
19+
*
20+
* % go run cmd/dijkstra-sp/main.go mediumEWD.txt 0
21+
* 0 to 0 (0.00)
22+
* 0 to 1 (0.71) 0->44 0.06 44->93 0.07 ... 107->1 0.07
23+
* 0 to 2 (0.65) 0->44 0.06 44->231 0.10 ... 42->2 0.11
24+
* 0 to 3 (0.46) 0->97 0.08 97->248 0.09 ... 45->3 0.12
25+
* 0 to 4 (0.42) 0->44 0.06 44->93 0.07 ... 77->4 0.11
26+
* ...
27+
*
28+
******************************************************************************/
29+
30+
package main
31+
32+
import (
33+
"fmt"
34+
"os"
35+
"strconv"
36+
37+
"github.com/shellfly/algo"
38+
"github.com/shellfly/algo/stdin"
39+
)
40+
41+
func main() {
42+
graph := algo.NewEdgeWeightedDigraph(stdin.NewIn(os.Args[1]))
43+
s, _ := strconv.Atoi(os.Args[2])
44+
sp := algo.NewDijkstraSP(graph, s)
45+
for t := 0; t < graph.V(); t++ {
46+
if sp.HasPathTo(t) {
47+
fmt.Printf("%d to %d (%.2f) ", s, t, sp.DistTo(t))
48+
for _, e := range sp.PathTo(t) {
49+
fmt.Print(e, " ")
50+
}
51+
fmt.Println()
52+
} else {
53+
fmt.Printf("%d to %d no path\n", s, t)
54+
}
55+
}
56+
}

cmd/edge-weighted-digraph/main.go

+11-11
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
/******************************************************************************
2-
* Execution: go run cmd/edge-weighted-graph/main.go filename.txt
2+
* Execution: go run cmd/edge-weighted-digraph/main.go filename.txt
33
* Data files: https://algs4.cs.princeton.edu/43mst/tinyEWG.txt
44
* https://algs4.cs.princeton.edu/43mst/mediumEWG.txt
55
* https://algs4.cs.princeton.edu/43mst/largeEWG.txt
66
*
77
* An edge-weighted undirected graph, implemented using adjacency lists.
88
* Parallel edges and self-loops are permitted.
99
*
10-
* % go run cmd/edge-weighted-graph/main.go tinyEWG.txt
11-
* 8 16
12-
* 0: 6-0 0.58000 0-2 0.26000 0-4 0.38000 0-7 0.16000
13-
* 1: 1-3 0.29000 1-2 0.36000 1-7 0.19000 1-5 0.32000
14-
* 2: 6-2 0.40000 2-7 0.34000 1-2 0.36000 0-2 0.26000 2-3 0.17000
15-
* 3: 3-6 0.52000 1-3 0.29000 2-3 0.17000
16-
* 4: 6-4 0.93000 0-4 0.38000 4-7 0.37000 4-5 0.35000
17-
* 5: 1-5 0.32000 5-7 0.28000 4-5 0.35000
18-
* 6: 6-4 0.93000 6-0 0.58000 3-6 0.52000 6-2 0.40000
19-
* 7: 2-7 0.34000 1-7 0.19000 0-7 0.16000 5-7 0.28000 4-7 0.37000
10+
* % go run cmd/edge-weighted-digraph/main.go tinyEWD.txt
11+
* 8 vertices, 15 edges
12+
* 0: 6-0 0.58000 0-2 0.26000 0-4 0.38000
13+
* 1: 1-3 0.29000 5-1 0.32000
14+
* 2: 6-2 0.40000 2-7 0.34000 0-2 0.26000
15+
* 3: 3-6 0.52000 1-3 0.29000 7-3 0.39000
16+
* 4: 6-4 0.93000 0-4 0.38000 4-7 0.37000 5-4 0.35000 4-5 0.35000
17+
* 5: 5-1 0.32000 7-5 0.28000 5-7 0.28000 5-4 0.35000 4-5 0.35000
18+
* 6: 6-4 0.93000 6-0 0.58000 3-6 0.52000 6-2 0.40000
19+
* 7: 2-7 0.34000 7-3 0.39000 7-5 0.28000 5-7 0.28000 4-7 0.37000
2020
*
2121
******************************************************************************/
2222

dijkstra_sp.go

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package algo
2+
3+
// PositiveInfinity is a fake positive infinity value
4+
const PositiveInfinity = 999999.0
5+
6+
// DijkstraSP ...
7+
type DijkstraSP struct {
8+
distTo []float32
9+
edgeTo []*DirectedEdge
10+
pq *IndexMinPQ
11+
}
12+
13+
// NewDijkstraSP ...
14+
func NewDijkstraSP(g *EdgeWeightedDigraph, s int) *DijkstraSP {
15+
edgeTo := make([]*DirectedEdge, g.V())
16+
distTo := make([]float32, g.V())
17+
for v := 0; v < g.V(); v++ {
18+
distTo[v] = PositiveInfinity
19+
}
20+
distTo[s] = 0.0
21+
pq := NewIndexMinPQ(g.V())
22+
d := &DijkstraSP{distTo, edgeTo, pq}
23+
24+
pq.Insert(s, FloatPQItem(distTo[s]))
25+
for !pq.IsEmpty() {
26+
d.relax(g, pq.DelMin())
27+
}
28+
29+
return d
30+
31+
}
32+
33+
func (d *DijkstraSP) relax(g *EdgeWeightedDigraph, v int) {
34+
for _, e := range g.Adj(v) {
35+
w := e.To()
36+
if d.distTo[w] > d.distTo[v]+e.Weight() {
37+
d.distTo[w] = d.distTo[v] + e.Weight()
38+
d.edgeTo[w] = e
39+
if d.pq.Contains(w) {
40+
d.pq.ChangeKey(w, FloatPQItem(d.distTo[w]))
41+
} else {
42+
d.pq.Insert(w, FloatPQItem(d.distTo[w]))
43+
}
44+
}
45+
}
46+
}
47+
48+
// DistTo ...
49+
func (d *DijkstraSP) DistTo(v int) float32 {
50+
return d.distTo[v]
51+
}
52+
53+
// HasPathTo ...
54+
func (d *DijkstraSP) HasPathTo(v int) bool {
55+
return d.distTo[v] < PositiveInfinity
56+
}
57+
58+
// PathTo ...
59+
func (d *DijkstraSP) PathTo(v int) (edges []*DirectedEdge) {
60+
if !d.HasPathTo(v) {
61+
return nil
62+
}
63+
64+
for e := d.edgeTo[v]; e != nil; e = d.edgeTo[e.From()] {
65+
// stack
66+
edges = append([]*DirectedEdge{e}, edges...)
67+
}
68+
return
69+
}

directed_edge.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func (e *DirectedEdge) To() int {
3030

3131
// String ...
3232
func (e *DirectedEdge) String() string {
33-
return fmt.Sprintf("%d-%d %.5f", e.v, e.w, e.weight)
33+
return fmt.Sprintf("%d->%d %.5f", e.v, e.w, e.weight)
3434
}
3535

3636
// CompareTo implements PQItem interface

edge_weighted_digraph.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func (g *EdgeWeightedDigraph) E() int {
4949

5050
// AddEdge ...
5151
func (g *EdgeWeightedDigraph) AddEdge(e *DirectedEdge) {
52-
g.adj[e.From()].Add(e.To())
52+
g.adj[e.From()].Add(e)
5353
g.e++
5454
}
5555

index_min_pq.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ func (mq *IndexMinPQ) Insert(i int, key PQItem) {
7676
// ChangeKey ...
7777
func (mq *IndexMinPQ) ChangeKey(i int, key PQItem) {
7878
mq.validateIndex(i)
79-
if mq.Contains(i) {
80-
panic("Index is alreay in the priority queue")
79+
if !mq.Contains(i) {
80+
panic("Index is not in the priority queue")
8181
}
8282

8383
mq.keys[i] = key

0 commit comments

Comments
 (0)