-
Notifications
You must be signed in to change notification settings - Fork 0
/
graph.go
147 lines (134 loc) · 2.8 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
// Package graph based on http://algs4.cs.princeton.edu/41graph/
package graph
import (
"bufio"
"bytes"
"fmt"
"io"
"strconv"
"strings"
"github.com/aukbit/cache/bag"
)
type Graph struct {
// number of vertices
v uint
// number of edges
e uint
// adj slice of bags, each contains vertices adjancents to a given vertex
adj []*bag.Bag
}
// New create a V-vertex graph with no edges
func New(vertex uint) *Graph {
return &Graph{
v: vertex,
adj: func() []*bag.Bag {
o := make([]*bag.Bag, vertex)
var i uint
for i = 0; i < vertex; i++ {
o[i] = bag.New()
}
return o
}(),
}
}
func atoui(s string) uint {
n, err := strconv.ParseUint(s, 10, 32)
if err != nil {
panic(err)
}
return uint(n)
}
// Load accepts io.Reader
// first line should contain number vertices
// second line should contain number edges
// next lines should contain a single edge v w
func Load(f io.Reader) (g *Graph, err error) {
var i int
var vertexes, edges uint
s := bufio.NewScanner(f)
for s.Scan() {
ln := s.Text()
if i == 0 {
// read number vertexes
vertexes = atoui(ln)
g = New(vertexes)
i++
continue
}
if i == 1 {
// read number edges
edges = atoui(ln)
i++
continue
}
e := strings.Split(ln, " ")
err = g.AddEdge(atoui(e[0]), atoui(e[1]))
if err != nil {
return nil, err
}
i++
}
// validate the number of edges on the file
if g.E() != edges {
return nil, fmt.Errorf("file does not contain the right number of edges %v != %v ", edges, g.E())
}
return g, nil
}
// V number of vertices
func (g *Graph) V() uint {
return g.v
}
// E number of edges
func (g *Graph) E() uint {
return g.e
}
func (g *Graph) validateVertex(v uint) error {
if v >= g.v {
return fmt.Errorf("invalid vertex %v >= %v", v, g.v)
}
return nil
}
// AddEdge add the undirected edge v-w to this graph
func (g *Graph) AddEdge(v, w uint) error {
if err := g.validateVertex(v); err != nil {
return err
}
if err := g.validateVertex(w); err != nil {
return err
}
g.e++
g.adj[v].Add(w)
g.adj[w].Add(v)
return nil
}
// Adj vertices adjancent to v
func (g *Graph) Adj(v uint) (*bag.Bag, error) {
if err := g.validateVertex(v); err != nil {
return nil, err
}
return g.adj[v], nil
}
// Degree returns the degree of vertex
func (g *Graph) Degree(v uint) (int, error) {
if err := g.validateVertex(v); err != nil {
return 0, err
}
return g.adj[v].Size(), nil
}
// String representation
func (g *Graph) String() string {
var buffer bytes.Buffer
buffer.WriteString(fmt.Sprintf("vertices: %v, edges: %v\n", g.v, g.e))
var i uint
for i = 0; i < g.v; i++ {
buffer.WriteString(fmt.Sprintf("%v: ", i))
iter := g.adj[i].Iterator()
for iter.HasNext() {
n, _ := iter.Next()
// fmt.Print(n)
buffer.WriteString(fmt.Sprintf("%v ", n))
}
buffer.WriteString("\n")
}
return buffer.String()
}