-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgraph.go
249 lines (210 loc) · 5.79 KB
/
graph.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
package goraph
import (
"sort"
)
// Graph is implemented by all of the graph types. All of the graph
// algorithms use this data type instead of the concrete types.
type Graph interface {
// AddVertex creates an returns a new vertex in the graph.
AddVertex() Vertex
// RemoveVertex permanently removes a vertex from the graph.
RemoveVertex(v Vertex)
// AddEdge adds an edge between u and v. If the graph is directional,
// then the edge will go from u to v.
AddEdge(u, v Vertex)
// RemoveEdge removes the edge between u and v.
RemoveEdge(u, v Vertex)
// Vertices returns a slice of the graph's vertices.
Vertices() []Vertex
// Edges returns a slice of the graph's edges.
Edges() []Edge
// Neighbours returns a slice of the vertices that neighbour v.
Neighbours(v Vertex) []Vertex
}
var (
_ Graph = &DirectedAdjacencyList{}
_ Graph = &AdjacencyList{}
)
// Vertex represents a node in the graph. Users should create
// new Vertex values with AddVertex.
type Vertex int
// Edge represents an edge between two vertices.
// In a directed graph, the edge is from U to V.
type Edge struct{ U, V Vertex }
// AdjacencyList implements an undirected graph using an adjacency list.
type AdjacencyList struct {
edges map[Vertex][]Vertex
nextVertex Vertex
}
// NewAdjacencyList creates an empty graph.
func NewAdjacencyList() *AdjacencyList {
return &AdjacencyList{edges: make(map[Vertex][]Vertex)}
}
func (g *AdjacencyList) AddVertex() Vertex {
v := g.nextVertex
g.edges[v] = make([]Vertex, 0)
g.nextVertex++
return v
}
func (g *AdjacencyList) RemoveVertex(v Vertex) {
delete(g.edges, v)
for vtx, vertices := range g.edges {
for idx, candidate := range vertices {
if candidate == v {
g.edges[vtx] = append(vertices[:idx], vertices[idx+1:len(vertices)]...)
}
}
}
}
func (g *AdjacencyList) AddEdge(u, v Vertex) {
if v < u {
u, v = v, u
}
edges := g.edges[u]
g.edges[u] = append(edges, v)
}
func (g *AdjacencyList) RemoveEdge(u, v Vertex) {
if v < u {
u, v = v, u
}
vertices, ok := g.edges[u]
if !ok {
return
}
for idx, vtx := range vertices {
if vtx == v {
// Remove the edge
g.edges[u] = append(vertices[:idx], vertices[idx+1:len(vertices)]...)
break
}
}
}
// VertexSlice is a convenience type for sorting vertices by ID.
type VertexSlice []Vertex
func (p VertexSlice) Len() int { return len(p) }
func (p VertexSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p VertexSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p VertexSlice) Sort() { sort.Sort(p) }
// EdgeSlice is a convenience type for sorting edges by ID.
type EdgeSlice []Edge
func (p EdgeSlice) Len() int { return len(p) }
func (p EdgeSlice) Less(i, j int) bool {
if p[i].U == p[j].U {
return p[i].V < p[j].V
} else {
return p[i].U < p[j].U
}
}
func (p EdgeSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p EdgeSlice) Sort() { sort.Sort(p) }
func (g *AdjacencyList) Vertices() []Vertex {
vertices := make(VertexSlice, len(g.edges))
var i int
for k := range g.edges {
vertices[i] = k
i++
}
return vertices
}
func (g *AdjacencyList) Edges() []Edge {
var edges []Edge
for k, neighbors := range g.edges {
for _, n := range neighbors {
edges = append(edges, Edge{k, n})
}
}
return edges
}
func (g *AdjacencyList) Neighbours(v Vertex) []Vertex {
return g.edges[v]
}
// DirectedAdjacencyList is like AdjacencyList, but directed.
type DirectedAdjacencyList struct {
edges map[Vertex][]Vertex
nextVertex Vertex
}
// NewDirectedAdjacencyList creates and initializes a DirectedAdjacencyList.
func NewDirectedAdjacencyList() *DirectedAdjacencyList {
g := &DirectedAdjacencyList{edges: make(map[Vertex][]Vertex)}
return g
}
// addVertex adds v to the graph in an idempotent fashion. The return value
// indicates whether or not the vertex was already in the graph; if false,
// the value was not in the graph before it was added.
func (g *DirectedAdjacencyList) addVertex(v Vertex) bool {
_, ok := g.edges[v]
if !ok {
g.edges[v] = make([]Vertex, 0)
}
return ok
}
// AddEdge connects vertices u and v in the graph.
func (g *DirectedAdjacencyList) AddEdge(u, v Vertex) {
g.addVertex(u)
g.addVertex(v)
g.edges[u] = append(g.edges[u], v)
}
func (g *DirectedAdjacencyList) RemoveEdge(u, v Vertex) {
vertices, ok := g.edges[u]
if !ok {
return
}
for idx, vtx := range vertices {
if vtx == v {
// Remove the edge
g.edges[u] = append(vertices[:idx], vertices[idx+1:len(vertices)]...)
break
}
}
}
func (g *DirectedAdjacencyList) AddVertex() Vertex {
v := g.nextVertex
g.addVertex(v)
g.nextVertex++
return v
}
func (g *DirectedAdjacencyList) RemoveVertex(v Vertex) {
delete(g.edges, v)
for vtx, vertices := range g.edges {
for idx, candidate := range vertices {
if candidate == v {
g.edges[vtx] = append(vertices[:idx], vertices[idx+1:len(vertices)]...)
}
}
}
}
func (g *DirectedAdjacencyList) Vertices() []Vertex {
vertices := make([]Vertex, 0, len(g.edges))
for k := range g.edges {
vertices = append(vertices, k)
}
return vertices
}
func (g *DirectedAdjacencyList) Edges() []Edge {
var edges []Edge
for k, neighbors := range g.edges {
for _, n := range neighbors {
edges = append(edges, Edge{k, n})
}
}
return edges
}
func (g *DirectedAdjacencyList) Neighbours(v Vertex) []Vertex {
return g.edges[v]
}
// Predecessors returns a slice of vertices that connect to v directionally.
func (g *DirectedAdjacencyList) Predecessors(v Vertex) (result []Vertex) {
for vtx, vertices := range g.edges {
for _, candidate := range vertices {
if candidate == v {
result = append(result, vtx)
}
}
}
return
}
// Successors returns a slice of vertices that v connects to directionally.
// This method returns the same thing as Neighbours.
func (g *DirectedAdjacencyList) Successors(v Vertex) []Vertex {
return g.edges[v]
}