-
Notifications
You must be signed in to change notification settings - Fork 1
/
graph.go
163 lines (138 loc) · 4.19 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
package grapho
import "sort"
// uint64Slice attaches the methods of sort.Interface to []uint64, sorting in increasing order.
type uint64Slice []uint64
func (p uint64Slice) Len() int { return len(p) }
func (p uint64Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p uint64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Attr is a set of attributes associated to a node/edge.
// Keys are strings. Values can be anything.
type Attr map[string]interface{}
// NewAttr creates an empty set of attributes.
func NewAttr() Attr {
return make(Attr)
}
// Edge represents a relationship between two nodes.
type Edge struct {
Weight int // Edge weight (cost)
Attr Attr // Edge attribute set
}
func NewEdge(weight int, attr Attr) *Edge {
if attr == nil {
attr = NewAttr()
}
return &Edge{weight, attr}
}
// Graph implementation. Each pair of nodes can only
// hold one edge between them (no parallel edges).
type Graph struct {
directed bool // true to represent a Digraph, false for Undirected Graphs
nodes map[uint64]Attr // Nodes present in the Graph, with their attributes
edges map[uint64]map[uint64]*Edge // Adjacency list of edges, with their attributes
}
// NewGraph creates an empty Graph.
func NewGraph(directed bool) *Graph {
return &Graph{
directed: directed,
nodes: make(map[uint64]Attr),
edges: make(map[uint64]map[uint64]*Edge),
}
}
// Len returns the number of nodes in the Graph
func (g *Graph) Len() int {
return len(g.nodes)
}
// IsDirected returns whether the Graph is directed or not.
func (g *Graph) IsDirected() bool { return g.directed }
// AddNode adds the given node to the Graph. If the node
// already exists, it will override its attributes.
func (g *Graph) AddNode(node uint64, attr Attr) {
if attr == nil {
attr = NewAttr()
}
g.nodes[node] = attr
g.edges[node] = make(map[uint64]*Edge)
}
// DeleteNode removes a node entry from the Graph.
// Any edge associated with it will be removed too.
func (g *Graph) DeleteNode(node uint64) {
// Remove incident edges
for k := range g.edges[node] {
delete(g.edges[k], node)
}
delete(g.edges, node)
delete(g.nodes, node)
}
// AddEdge adds an edge (with its attributes) between nodes u and v
// If the nodes don't exist, they will be automatically created.
// If an u-v edge already existed, its attributes will be overridden.
func (g *Graph) AddEdge(u, v uint64, weight int, attr Attr) {
// Add nodes if necessary
if _, ok := g.nodes[u]; !ok {
g.AddNode(u, nil)
}
if _, ok := g.nodes[v]; !ok {
g.AddNode(v, nil)
}
edge := NewEdge(weight, attr)
g.edges[u][v] = edge
if !g.directed {
g.edges[v][u] = edge
}
}
// DeleteEdge removes the u-v edge, if exists.
// If any of the nodes don't exist, nothing happens.
func (g *Graph) DeleteEdge(u, v uint64) {
if _, ok := g.Node(u); ok {
if _, ok := g.Node(v); ok {
delete(g.edges[u], v)
if !g.directed {
delete(g.edges[v], u)
}
}
}
}
// Nodes returns the list of nodes in the Graph (unsorted).
func (g *Graph) Nodes() []uint64 {
nodes := make([]uint64, len(g.nodes))
n := 0
for k := range g.nodes {
nodes[n] = k
n++
}
return nodes
}
// Node returns the attributes associated with a given node, and
// a bool flag set to true if the node was found, false otherwise.
func (g *Graph) Node(node uint64) (Attr, bool) {
attr, ok := g.nodes[node]
return attr, ok
}
// Neighbors returns the list of nodes containing edges between the
// given node and them, ordered by ascending node uint64 value
// An extra bool flag determines whether the node was found.
func (g *Graph) Neighbors(node uint64) ([]uint64, bool) {
if edges, ok := g.edges[node]; ok {
nodes := make([]uint64, len(edges))
n := 0
for k := range edges {
nodes[n] = k
n++
}
sort.Sort(uint64Slice(nodes)) // order by node uint64 value
return nodes, true
}
return nil, false
}
// Edge returns the Edge associated with the u-v node pair.
// An extra bool flag determines whether the edge was found.
// In undirected graphs, the edge u-v is be the same as v-u.
func (g *Graph) Edge(u, v uint64) (*Edge, bool) {
if _, ok := g.Node(u); ok {
if _, ok := g.Node(v); ok {
edge, ok := g.edges[u][v]
return edge, ok
}
}
return nil, false
}