Skip to content

Commit ac2f361

Browse files
committedNov 6, 2024
feat: add graph struct
1 parent 686cbb7 commit ac2f361

File tree

5 files changed

+142
-1
lines changed

5 files changed

+142
-1
lines changed
 

‎Readme.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ it's some data struct using golang
88
- [x] Stack
99
- [x] Queue
1010
- [x] Heap
11-
- [ ] B/B+ tree
11+
- [ ] B/B+ tree
12+
- [x] Graph

‎go.mod

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
module github.com/haokunt/go-data-struct
22

33
go 1.14
4+
5+
require github.com/stretchr/testify v1.9.0

‎go.sum

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
5+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
6+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
7+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
8+
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
9+
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
10+
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
11+
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
12+
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
13+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
14+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
15+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
16+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
17+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
18+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
19+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

‎graph.go

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package datastruct
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
// Vertex is a node in graph
8+
type Vertex struct {
9+
Name string
10+
Value interface{}
11+
}
12+
13+
// Edge is a connection between two verties
14+
type Edge struct {
15+
Cost float64
16+
From string // the name of start vertex
17+
To string // the name of end vertex
18+
}
19+
20+
// Graph is a collection of verties and edges
21+
type Graph struct {
22+
//we need use map instead of list, because we need make sure the node name/id will not be duplicated
23+
verties map[string]*Vertex
24+
edges []*Edge
25+
}
26+
27+
// NewGraph creates a new graph
28+
func NewGraph(verties []*Vertex, edges []*Edge) (*Graph, error) {
29+
g := new(Graph)
30+
vx := make(map[string]*Vertex)
31+
for _, v := range verties {
32+
vx[v.Name] = v
33+
}
34+
for _, e := range edges {
35+
_, okf := vx[e.From]
36+
_, okt := vx[e.To]
37+
if !okf || !okt {
38+
return nil, fmt.Errorf("invalid edge: %v", e)
39+
}
40+
}
41+
g.verties = vx
42+
g.edges = edges
43+
return g, nil
44+
}
45+
46+
// AddVertext adds a vertex to the graph
47+
func (g *Graph) AddVertext(vertex *Vertex) error {
48+
if _, ok := g.verties[vertex.Name]; ok {
49+
return fmt.Errorf("duplicated vertex name: %s", vertex.Name)
50+
}
51+
g.verties[vertex.Name] = vertex
52+
return nil
53+
}
54+
55+
// AddEdge adds an edge to the graph
56+
func (g *Graph) AddEdge(edge *Edge) error {
57+
if _, ok := g.verties[edge.From]; !ok {
58+
return fmt.Errorf("invalid edge: %v", edge)
59+
}
60+
if _, ok := g.verties[edge.To]; !ok {
61+
return fmt.Errorf("invalid edge: %v", edge)
62+
}
63+
g.edges = append(g.edges, edge)
64+
return nil
65+
}

‎graph_test.go

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package datastruct
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestNewGraph(t *testing.T) {
10+
verties := []*Vertex{
11+
{Name: "A", Value: 1},
12+
{Name: "B", Value: 2},
13+
}
14+
edges := []*Edge{
15+
{Cost: 1.0, From: "A", To: "B"},
16+
}
17+
18+
graph, err := NewGraph(verties, edges)
19+
assert.NoError(t, err)
20+
assert.Equal(t, 2, len(graph.verties))
21+
assert.Equal(t, 1, len(graph.edges))
22+
}
23+
24+
func TestAddVertext(t *testing.T) {
25+
graph, _ := NewGraph([]*Vertex{}, []*Edge{})
26+
27+
vertex := &Vertex{Name: "A", Value: 1}
28+
err := graph.AddVertext(vertex)
29+
assert.NoError(t, err)
30+
assert.Equal(t, 1, len(graph.verties))
31+
32+
// Test adding duplicate vertex
33+
err = graph.AddVertext(vertex)
34+
assert.Error(t, err)
35+
}
36+
37+
func TestAddEdge(t *testing.T) {
38+
verties := []*Vertex{
39+
{Name: "A", Value: 1},
40+
{Name: "B", Value: 2},
41+
}
42+
graph, _ := NewGraph(verties, []*Edge{})
43+
44+
edge := &Edge{Cost: 1.0, From: "A", To: "B"}
45+
err := graph.AddEdge(edge)
46+
assert.NoError(t, err)
47+
48+
assert.Equal(t, 1, len(graph.edges))
49+
50+
// Test adding edge with invalid vertex
51+
invalidEdge := &Edge{Cost: 1.0, From: "A", To: "C"}
52+
err = graph.AddEdge(invalidEdge)
53+
assert.Error(t, err)
54+
}

0 commit comments

Comments
 (0)
Please sign in to comment.