...
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 VisitableGraph interface {
17 graph.Graph
18
19
20
21 VisitFrom(from graph.Node, visitor func(graph.Node) (shouldContinue bool))
22 }
23
24
25 type VisitingDepthFirst struct {
26 EdgeFilter func(graph.Edge) bool
27 Visit func(u, v graph.Node)
28 stack linear.NodeStack
29 visited *intsets.Sparse
30 }
31
32
33
34
35
36
37 func (d *VisitingDepthFirst) Walk(g VisitableGraph, from graph.Node, until func(graph.Node) bool) graph.Node {
38 if d.visited == nil {
39 d.visited = &intsets.Sparse{}
40 }
41 d.stack.Push(from)
42 d.visited.Insert(from.ID())
43 if until != nil && until(from) {
44 return from
45 }
46
47 var found graph.Node
48 for d.stack.Len() > 0 {
49 t := d.stack.Pop()
50 g.VisitFrom(t, func(n graph.Node) (shouldContinue bool) {
51 if d.EdgeFilter != nil && !d.EdgeFilter(g.Edge(t, n)) {
52 return true
53 }
54 if d.visited.Has(n.ID()) {
55 return true
56 }
57 if d.Visit != nil {
58 d.Visit(t, n)
59 }
60 d.visited.Insert(n.ID())
61 d.stack.Push(n)
62 if until != nil && until(n) {
63 found = n
64 return false
65 }
66 return true
67 })
68 if found != nil {
69 return found
70 }
71 }
72 return nil
73 }
74
75
76 func (d *VisitingDepthFirst) Visited(n graph.Node) bool {
77 return d.visited != nil && d.visited.Has(n.ID())
78 }
79
80
81 func (d *VisitingDepthFirst) Reset() {
82 d.stack = d.stack[:0]
83 if d.visited != nil {
84 d.visited.Clear()
85 }
86 }
87
View as plain text