data_structures_rmolinari 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8d63f6987f160f00ce92f79643f904f95bc230e4a5b60679f4301ecd366622a
|
4
|
+
data.tar.gz: cdc660ab53a0259a79b72ecc3928f640faa7b1251a1bae3baabb1c70bac20d01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 057d29af42606c7ecc4a78e6c752fa5f7a29b41788f21ca7ede6bab0893d1ba63b6c9dc3e5f3b5747f3912718565d6dfcb5952d189f78b40a6ef77efe95f34c9
|
7
|
+
data.tar.gz: '08f6921ab4b1c7cf84c9fe5624266b7060f4f1d4f1ecc56e3850106b3bb30e0c6b30c3ea808a61939966350118684f3353ccbb628d24b353b35ae865268222d2'
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# A "disjoint set union" that represents a set of elements that belonging to _disjoint_ subsets. Alternatively, this expresses a
|
2
|
+
# partion of a fixed set.
|
3
|
+
#
|
4
|
+
# The data structure provides efficient actions to merge two disjoint subsets, i.e., replace them by their union, and determine if
|
5
|
+
# two elements are in the same subset.
|
6
|
+
#
|
7
|
+
# The elements of the set must be 0, 1, ..., n-1. Client code can map its data to these representatives. The code uses several ideas
|
8
|
+
# from Tarjan and van Leeuwen for efficiency
|
9
|
+
#
|
10
|
+
# See https://en.wikipedia.org/wiki/Disjoint-set_data_structure for a good introduction.
|
11
|
+
#
|
12
|
+
# - Tarjan, Robert E., van Leeuwen, Jan (1984). "Worst-case analysis of set union algorithms". Journal of the ACM. 31 (2): 245–281.
|
13
|
+
class DisjointUnionInternal
|
14
|
+
attr_reader :subset_count
|
15
|
+
|
16
|
+
# @param size the size of the universe, which must be known at the time of construction. The elements 0, 1, ..., size - 1 start
|
17
|
+
# out in disjoint singleton subsets.
|
18
|
+
def initialize(size)
|
19
|
+
@size = size
|
20
|
+
# Initialize to
|
21
|
+
@d = (0...size).to_a
|
22
|
+
@rank = [0] * size
|
23
|
+
|
24
|
+
@subset_count = size
|
25
|
+
end
|
26
|
+
|
27
|
+
# Declare that e and f are equivalent, i.e., in the same subset. If they are already in the same subset this is a no-op.
|
28
|
+
#
|
29
|
+
# Each argument must be one of 0, 1, ..., size-1.
|
30
|
+
def unite(e, f)
|
31
|
+
check_value(e)
|
32
|
+
check_value(f)
|
33
|
+
raise 'Uniting an element with itself is meaningless' if e == f
|
34
|
+
|
35
|
+
e_root = find(e)
|
36
|
+
f_root = find(f)
|
37
|
+
return if e_root == f_root
|
38
|
+
|
39
|
+
@subset_count -= 1
|
40
|
+
link(e_root, f_root)
|
41
|
+
end
|
42
|
+
|
43
|
+
# The canonical representative of the subset containing e. Two elements d and e are in the same subset exactly when find(d) ==
|
44
|
+
# find(e).
|
45
|
+
# @param e must be one of 0, 1, ..., size-1.
|
46
|
+
# @return (Integer) one of 0, 1, ..., size-1.
|
47
|
+
def find(e)
|
48
|
+
# We implement find with "halving" to shrink the length of paths to the root. See Tarjan and van Leeuwin p 252.
|
49
|
+
x = e
|
50
|
+
x = @d[x] = @d[@d[x]] while @d[@d[x]] != @d[x]
|
51
|
+
@d[x]
|
52
|
+
end
|
53
|
+
|
54
|
+
private def check_value(v)
|
55
|
+
raise "Value must be given and be in (0..#{@size - 1})" unless v && v.between?(0, @size - 1)
|
56
|
+
end
|
57
|
+
|
58
|
+
private def link(e, f)
|
59
|
+
# Choose which way around to do the linking using the element "ranks". See Tarjan and van Leeuwen, p 250.
|
60
|
+
if @rank[e] > @rank[f]
|
61
|
+
@d[f] = e
|
62
|
+
elsif @rank[e] == @rank[f]
|
63
|
+
@d[f] = e
|
64
|
+
@rank[e] += 1
|
65
|
+
else
|
66
|
+
@d[e] = f
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative 'data_structures_rmolinari/shared'
|
2
|
+
require_relative 'data_structures_rmolinari/disjoint_union_internal'
|
2
3
|
require_relative 'data_structures_rmolinari/generic_segment_tree_internal'
|
3
4
|
require_relative 'data_structures_rmolinari/heap_internal'
|
4
5
|
require_relative 'data_structures_rmolinari/max_priority_search_tree_internal'
|
@@ -11,6 +12,7 @@ module DataStructuresRMolinari
|
|
11
12
|
# Priority Search Trees
|
12
13
|
#
|
13
14
|
# Note that MinmaxPrioritySearchTree is only a fragment of what we need
|
15
|
+
|
14
16
|
MaxPrioritySearchTree = MaxPrioritySearchTreeInternal
|
15
17
|
MinmaxPrioritySearchTree = MinmaxPrioritySearchTreeInternal
|
16
18
|
|
@@ -42,5 +44,11 @@ module DataStructuresRMolinari
|
|
42
44
|
|
43
45
|
########################################
|
44
46
|
# Heap
|
47
|
+
|
45
48
|
Heap = HeapInternal
|
49
|
+
|
50
|
+
########################################
|
51
|
+
# Disjoint Union
|
52
|
+
|
53
|
+
DisjointUnion = DisjointUnionInternal
|
46
54
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: data_structures_rmolinari
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rory Molinari
|
@@ -72,12 +72,15 @@ description: |
|
|
72
72
|
Sometimes it is not enough to read the description of a data structure and accompanying pseudo-code.
|
73
73
|
Actually implementing the structure is often helpful in understanding what is going on. It is also
|
74
74
|
usually fun.
|
75
|
+
|
76
|
+
We implement Disjoin Union, Heap, Priority Search Tree, and Segment Tree.
|
75
77
|
email: rorymolinari+rubygems@gmail.com
|
76
78
|
executables: []
|
77
79
|
extensions: []
|
78
80
|
extra_rdoc_files: []
|
79
81
|
files:
|
80
82
|
- lib/data_structures_rmolinari.rb
|
83
|
+
- lib/data_structures_rmolinari/disjoint_union_internal.rb
|
81
84
|
- lib/data_structures_rmolinari/generic_segment_tree_internal.rb
|
82
85
|
- lib/data_structures_rmolinari/heap_internal.rb
|
83
86
|
- lib/data_structures_rmolinari/max_priority_search_tree_internal.rb
|