-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathdisjointsetll.go
162 lines (148 loc) · 3.55 KB
/
disjointsetll.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
package disjointset
import (
"fmt"
)
/**
* Node for the linked list
*/
type DisjointSetLLNode struct {
id int
next *DisjointSetLLNode
}
/**
* Each component of the disjoint set.
* Contains the id of the region, its parent (if the parent has the same
* address, it means that it's the root), a pointer to the last element of the
* LL, a pointer to the first element of the LL and the size of the region
*/
type DisjointSetLLRegion struct {
id int
parent *DisjointSetLLRegion
head *DisjointSetLLNode
last *DisjointSetLLNode
size int
rank int
}
/**
* DisjointSetLL datatype, it contains a list of all the regions and
* the number of components that it's storing
*/
type DisjointSetLL struct {
regions []*DisjointSetLLRegion
totalComponents int
}
/**
* Instantiates a new DisjointSetLL with 'size' elements
*/
func NewDisjointSetLL(size int) *DisjointSetLL {
set := new(DisjointSetLL)
set.regions = make([]*DisjointSetLLRegion, size, size)
for i, _ := range set.regions {
set.regions[i] = new(DisjointSetLLRegion)
region := set.regions[i]
region.id = i
region.parent = region
region.size = 1
region.rank = 0
region.head = new(DisjointSetLLNode)
region.head.id = i
region.head.next = region.head
region.last = region.head
}
set.totalComponents = size
return set
}
/**
* Return the number of components that are stored
*/
func (set *DisjointSetLL) TotalComponents() int {
return set.totalComponents
}
/**
* Return the number of elements that are stored
*/
func (set *DisjointSetLL) TotalElements() int {
return len(set.regions)
}
/**
* Returns the id of the component to which the node v belongs
*/
func (set *DisjointSetLL) Find(v int) int {
var findNode func(int) *DisjointSetLLRegion
findNode = func(v int) *DisjointSetLLRegion {
if set.regions[v].parent.id != v {
set.regions[v].parent = findNode(set.regions[v].parent.id)
}
return set.regions[v].parent
}
return findNode(v).id
}
/**
* Return the size of the region that v belongs to
*/
func (set *DisjointSetLL) Size(v int) int {
return set.regions[set.Find(v)].size
}
/*
* Merge the regions that a and b belong to
*/
func (set *DisjointSetLL) Union(a, b int) {
region1 := set.regions[set.Find(a)]
region2 := set.regions[set.Find(b)]
if region1.id == region2.id {
return
}
set.totalComponents--
if region1.rank < region2.rank {
region2.head, region1.last.next = region1.head, region2.head
region2.last.next = region2.head
region2.size += region1.size
region1.parent = region2
} else {
region1.head, region2.last.next = region2.head, region1.head
region1.last.next = region1.head
region1.size += region2.size
region2.parent = region1
if region1.rank == region2.rank {
region1.rank++
}
}
}
/**
* Returns all the elements that belong too the region that v belongs to
*/
func (set *DisjointSetLL) Elements(v int) chan int {
ch := make(chan int)
go func() {
region := set.Find(v)
node := set.regions[region].head
ch <- node.id
for set.regions[region].head != node.next {
ch <- node.next.id
node = node.next
}
close(ch)
}()
return ch
}
/**
* Returns true if a and b belong to the same region
*/
func (set *DisjointSetLL) Connected(a, b int) bool {
return set.Find(a) == set.Find(b)
}
/**
* Print the dijsointset linked list
*/
func (set *DisjointSetLL) Print() {
for v := 0; v < len(set.regions); v++ {
region := set.Find(v)
if region == v {
fmt.Printf("%d : ", region)
for e := range set.Elements(region) {
fmt.Printf("%d -> ", e)
}
fmt.Printf("(%d)\n", set.regions[region].last.next.id)
}
}
}