-
Notifications
You must be signed in to change notification settings - Fork 96
/
sort.go
79 lines (65 loc) · 1.36 KB
/
sort.go
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
package hero
// sort implements topological sort.
type sort struct {
vertices map[string]struct{}
graph map[string]map[string]struct{}
v map[string]int
}
func newSort() *sort {
return &sort{
vertices: make(map[string]struct{}),
graph: make(map[string]map[string]struct{}),
v: make(map[string]int),
}
}
func (s *sort) addVertices(vertices ...string) {
for _, vertex := range vertices {
s.vertices[vertex] = struct{}{}
}
}
func (s *sort) addEdge(from, to string) {
if _, ok := s.graph[from]; !ok {
s.graph[from] = map[string]struct{}{
to: {},
}
} else {
s.graph[from][to] = struct{}{}
}
}
func (s *sort) collect(queue *[]string) {
for vertex, count := range s.v {
if count == 0 {
*queue = append(*queue, vertex)
delete(s.v, vertex)
}
}
}
// sort returns sorted string list.
func (s *sort) sort() []string {
for vertex := range s.vertices {
s.v[vertex] = 0
}
for _, tos := range s.graph {
for to := range tos {
s.v[to]++
}
}
r := make([]string, 0, len(s.vertices))
queue := make([]string, 0, len(s.vertices))
s.collect(&queue)
for len(queue) > 0 {
r = append(r, queue[0])
if tos, ok := s.graph[queue[0]]; ok {
for to := range tos {
s.v[to]--
}
}
s.collect(&queue)
delete(s.graph, queue[0])
queue = queue[1:]
}
if len(s.v) > 0 {
panic("import or include cycle")
}
return r
}