...
1
2
3
4
5
6 package traverse
7
8 import (
9 "golang.org/x/tools/container/intsets"
10
11 "k8s.io/kubernetes/third_party/forked/gonum/graph"
12 "k8s.io/kubernetes/third_party/forked/gonum/graph/internal/linear"
13 )
14
15
16 type BreadthFirst struct {
17 EdgeFilter func(graph.Edge) bool
18 Visit func(u, v graph.Node)
19 queue linear.NodeQueue
20 visited *intsets.Sparse
21 }
22
23
24
25
26
27
28 func (b *BreadthFirst) Walk(g graph.Graph, from graph.Node, until func(n graph.Node, d int) bool) graph.Node {
29 if b.visited == nil {
30 b.visited = &intsets.Sparse{}
31 }
32 b.queue.Enqueue(from)
33 b.visited.Insert(from.ID())
34
35 var (
36 depth int
37 children int
38 untilNext = 1
39 )
40 for b.queue.Len() > 0 {
41 t := b.queue.Dequeue()
42 if until != nil && until(t, depth) {
43 return t
44 }
45 for _, n := range g.From(t) {
46 if b.EdgeFilter != nil && !b.EdgeFilter(g.Edge(t, n)) {
47 continue
48 }
49 if b.visited.Has(n.ID()) {
50 continue
51 }
52 if b.Visit != nil {
53 b.Visit(t, n)
54 }
55 b.visited.Insert(n.ID())
56 children++
57 b.queue.Enqueue(n)
58 }
59 if untilNext--; untilNext == 0 {
60 depth++
61 untilNext = children
62 children = 0
63 }
64 }
65
66 return nil
67 }
68
69
70
71
72
73 func (b *BreadthFirst) WalkAll(g graph.Undirected, before, after func(), during func(graph.Node)) {
74 b.Reset()
75 for _, from := range g.Nodes() {
76 if b.Visited(from) {
77 continue
78 }
79 if before != nil {
80 before()
81 }
82 b.Walk(g, from, func(n graph.Node, _ int) bool {
83 if during != nil {
84 during(n)
85 }
86 return false
87 })
88 if after != nil {
89 after()
90 }
91 }
92 }
93
94
95 func (b *BreadthFirst) Visited(n graph.Node) bool {
96 return b.visited != nil && b.visited.Has(n.ID())
97 }
98
99
100 func (b *BreadthFirst) Reset() {
101 b.queue.Reset()
102 if b.visited != nil {
103 b.visited.Clear()
104 }
105 }
106
107
108 type DepthFirst struct {
109 EdgeFilter func(graph.Edge) bool
110 Visit func(u, v graph.Node)
111 stack linear.NodeStack
112 visited *intsets.Sparse
113 }
114
115
116
117
118
119
120 func (d *DepthFirst) Walk(g graph.Graph, from graph.Node, until func(graph.Node) bool) graph.Node {
121 if d.visited == nil {
122 d.visited = &intsets.Sparse{}
123 }
124 d.stack.Push(from)
125 d.visited.Insert(from.ID())
126
127 for d.stack.Len() > 0 {
128 t := d.stack.Pop()
129 if until != nil && until(t) {
130 return t
131 }
132 for _, n := range g.From(t) {
133 if d.EdgeFilter != nil && !d.EdgeFilter(g.Edge(t, n)) {
134 continue
135 }
136 if d.visited.Has(n.ID()) {
137 continue
138 }
139 if d.Visit != nil {
140 d.Visit(t, n)
141 }
142 d.visited.Insert(n.ID())
143 d.stack.Push(n)
144 }
145 }
146
147 return nil
148 }
149
150
151
152
153
154 func (d *DepthFirst) WalkAll(g graph.Undirected, before, after func(), during func(graph.Node)) {
155 d.Reset()
156 for _, from := range g.Nodes() {
157 if d.Visited(from) {
158 continue
159 }
160 if before != nil {
161 before()
162 }
163 d.Walk(g, from, func(n graph.Node) bool {
164 if during != nil {
165 during(n)
166 }
167 return false
168 })
169 if after != nil {
170 after()
171 }
172 }
173 }
174
175
176 func (d *DepthFirst) Visited(n graph.Node) bool {
177 return d.visited != nil && d.visited.Has(n.ID())
178 }
179
180
181 func (d *DepthFirst) Reset() {
182 d.stack = d.stack[:0]
183 if d.visited != nil {
184 d.visited.Clear()
185 }
186 }
187
View as plain text