This repository has been archived by the owner on Jun 22, 2021. It is now read-only.
/
graph.go
120 lines (106 loc) · 2.22 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
package graph
import (
"github.com/RIscRIpt/bitarray"
"github.com/RIscRIpt/dllist"
)
type NodeHolder uint32
const (
HT_None NodeHolder = iota
HT_AdjacencyList
HT_AdjacencyMatrix
)
type Graph struct {
Root *Node
holder nodeHolder
nodes map[uint32]*Node
}
type nodeHolder interface {
adjacent(n uint32) []uint32
connect(n1, n2 uint32)
String() string
}
func NewGraph(ht NodeHolder, initialSize uint32) (g *Graph) {
g = &Graph{}
switch ht {
case HT_AdjacencyList:
g.holder = newAdjacencyList(initialSize)
case HT_AdjacencyMatrix:
g.holder = newAdjacencyMatrix(initialSize)
default:
panic("Unsupported node holder type")
}
g.nodes = make(map[uint32]*Node)
return
}
func (g *Graph) AddNode(value interface{}) uint32 {
node := NewNode(uint32(len(g.nodes)), value)
if g.Root == nil {
g.Root = node
}
g.nodes[node.id] = node
return node.id
}
func (g *Graph) AdjacencyList() (list map[*Node][]*Node) {
list = make(map[*Node][]*Node)
for _, n := range g.nodes {
list[n] = append(list[n], g.Adjacent(n)...)
}
return
}
func (g *Graph) Adjacent(n *Node) (adj []*Node) {
for _, i := range g.holder.adjacent(n.id) {
adj = append(adj, g.nodes[i])
}
return
}
func (g *Graph) Connect(n1, n2 uint32) {
g.holder.connect(n1, n2)
}
func (g *Graph) String() string {
return g.holder.String()
}
func (g *Graph) ConnectNodes(n1, n2 *Node) {
g.Connect(n1.id, n2.id)
g.nodes[n1.id] = n1
g.nodes[n2.id] = n2
}
func (g *Graph) BFS() (path []*Node) {
visited := bitarray.NewBitArray(uint32(len(g.nodes)), 1)
queue := dllist.New()
queue.PushBack(g.Root)
for queue.Length() > 0 {
m, err := queue.PopFront()
if err != nil {
break
}
n := m.(*Node)
if visited.GetB(n.id) == 0 {
visited.SetB(n.id, 1)
path = append(path, n)
for _, c := range g.Adjacent(n) {
queue.PushBack(c)
}
}
}
return
}
func (g *Graph) DFS() (path []*Node) {
visited := bitarray.NewBitArray(uint32(len(g.nodes)), 1)
stack := dllist.New()
stack.PushFront(g.Root)
for stack.Length() > 0 {
m, err := stack.PopFront()
if err != nil {
panic(err)
}
n := m.(*Node)
if visited.GetB(n.id) == 0 {
path = append(path, n)
visited.SetB(n.id, 1)
for _, c := range g.Adjacent(n) {
stack.PushFront(c)
}
}
}
return
}