Skip to content

Commit 153f289

Browse files
committed
add depth first paths
1 parent f1ef58a commit 153f289

File tree

4 files changed

+119
-1
lines changed

4 files changed

+119
-1
lines changed

cmd/depth-first-paths/main.go

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
Execution: go run cmd/depth-first-paths/main.go G s
3+
4+
Data files: https://algs4.cs.princeton.edu/41graph/tinyCG.txt
5+
https://algs4.cs.princeton.edu/41graph/tinyG.txt
6+
https://algs4.cs.princeton.edu/41graph/mediumG.txt
7+
https://algs4.cs.princeton.edu/41graph/largeG.txt
8+
9+
Run depth first search on an undirected graph.
10+
Runs in O(E + V) time.
11+
12+
% go run cmd/graph/main.go tinyCG.txt
13+
6 8
14+
0: 2 1 5
15+
1: 0 2
16+
2: 0 1 3 4
17+
3: 5 4 2
18+
4: 3 2
19+
5: 3 0
20+
21+
% go run cmd/depth-first-paths/main.go tinyCG.txt 0
22+
0 to 0: 0
23+
0 to 1: 0-2-1
24+
0 to 2: 0-2
25+
0 to 3: 0-2-3
26+
0 to 4: 0-2-3-4
27+
0 to 5: 0-2-3-5
28+
29+
*/
30+
31+
package main
32+
33+
import (
34+
"fmt"
35+
"os"
36+
"strconv"
37+
38+
"github.com/shellfly/algo"
39+
"github.com/shellfly/algo/stdin"
40+
)
41+
42+
func main() {
43+
graph := algo.NewGraph(stdin.NewIn(os.Args[1]))
44+
s, _ := strconv.Atoi(os.Args[2])
45+
p := algo.NewDepthFirstPaths(graph, s)
46+
47+
for v := 0; v < graph.V(); v++ {
48+
if p.HasPathTo(v) {
49+
fmt.Printf("%d to %d: ", s, v)
50+
for _, x := range p.PathTo(v) {
51+
if x == s {
52+
fmt.Print(x)
53+
} else {
54+
fmt.Printf("-%d", x)
55+
}
56+
}
57+
fmt.Println()
58+
} else {
59+
fmt.Printf("%d and %d: not connected\n", s, v)
60+
}
61+
}
62+
63+
}

depth_first_paths.go

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package algo
2+
3+
// DepthFirstPaths ...
4+
type DepthFirstPaths struct {
5+
marked []bool
6+
edgeTo []int
7+
s int
8+
}
9+
10+
// NewDepthFirstPaths ...
11+
func NewDepthFirstPaths(g *Graph, s int) *DepthFirstPaths {
12+
dfs := &DepthFirstPaths{marked: make([]bool, g.V()), edgeTo: make([]int, g.V()), s: s}
13+
dfs.Dfs(g, s)
14+
return dfs
15+
}
16+
17+
// Dfs ...
18+
func (s *DepthFirstPaths) Dfs(g *Graph, v int) {
19+
s.marked[v] = true
20+
for _, w := range g.Adj(v) {
21+
if !s.marked[w] {
22+
s.edgeTo[w] = v
23+
s.Dfs(g, w)
24+
}
25+
}
26+
}
27+
28+
// HasPathTo ...
29+
func (s *DepthFirstPaths) HasPathTo(v int) bool {
30+
return s.marked[v]
31+
}
32+
33+
// PathTo ...
34+
func (s *DepthFirstPaths) PathTo(v int) []int {
35+
if !s.HasPathTo(v) {
36+
return nil
37+
}
38+
path := NewStack()
39+
for x := v; x != s.s; x = s.edgeTo[x] {
40+
path.Push(x)
41+
}
42+
path.Push(s.s)
43+
vertexes := []int{}
44+
for _, x := range path.Slice() {
45+
vertexes = append(vertexes, x.(int))
46+
}
47+
return vertexes
48+
}

graph.go

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ func NewGraph(in *stdin.In) *Graph {
2121
}
2222
g := &Graph{v: v, e: 0, adj: adj}
2323
e := in.ReadInt()
24-
fmt.Println(v, e)
2524
for i := 0; i < e; i++ {
2625
v, w := in.ReadInt(), in.ReadInt()
2726
g.AddEdge(v, w)

stack.go

+8
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,11 @@ func (s *Stack) Pop() (item interface{}) {
3838
func (s Stack) Size() int {
3939
return s.n
4040
}
41+
42+
// Slice ...
43+
func (s Stack) Slice() (items []interface{}) {
44+
for !s.IsEmpty() {
45+
items = append(items, s.Pop())
46+
}
47+
return
48+
}

0 commit comments

Comments
 (0)