splaytree 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d251409b924ce93ff916bf31539babb39da6ff50
4
+ data.tar.gz: 96ce8b423c24cc2cdc21d8e9a3afe04f89aaae78
5
+ SHA512:
6
+ metadata.gz: 9815b103c477f5fccde78d85fd48c00b89b13aa0162495fe53eeb843c96cb4bb36721d260d687ae35d41fbf2981e8a5f68fe452b5d46663f908d171a319da07a
7
+ data.tar.gz: ac6a350fd0a2a98df6bf46dde19837c84fd8ed34499410629f3840bdb3b365896aacedd75971298423f052e020d93ddfb9f702386d582c693334be9fa349dbcb
@@ -0,0 +1,103 @@
1
+ class Splaytree
2
+ class Node
3
+ include Comparable
4
+
5
+ attr_reader :key
6
+ attr_accessor :value, :left, :right, :parent, :duplicates
7
+
8
+ def initialize(key, value = nil, parent = nil, left = nil, right = nil)
9
+ @key = key
10
+ @value = value
11
+ @parent = parent
12
+ @left = left
13
+ @right = right
14
+ @duplicates = []
15
+ end
16
+
17
+ def add_duplicate!(value)
18
+ @duplicates.push(@value)
19
+ @value = value
20
+ end
21
+
22
+ def remove_duplicate!
23
+ return if @duplicates.empty?
24
+ deleted = @value
25
+ @value = @duplicates.pop
26
+ deleted
27
+ end
28
+
29
+ def has_duplicates?
30
+ @duplicates.length > 0
31
+ end
32
+
33
+ def root?
34
+ parent.nil?
35
+ end
36
+
37
+ def parent_root?
38
+ parent && parent.root?
39
+ end
40
+
41
+ def gparent
42
+ parent && parent.parent
43
+ end
44
+
45
+ def set_left(node)
46
+ @left = node
47
+ return unless node
48
+ node.parent = self
49
+ end
50
+
51
+ def set_right(node)
52
+ @right = node
53
+ return unless node
54
+ node.parent = self
55
+ end
56
+
57
+ def rotate
58
+ parent = self.parent
59
+ gparent = self.gparent
60
+ if gparent
61
+ if parent.object_id == gparent.left.object_id
62
+ gparent.set_left(self)
63
+ else
64
+ gparent.set_right(self)
65
+ end
66
+ else
67
+ self.parent = nil
68
+ end
69
+
70
+ if self.object_id == parent.left.object_id
71
+ parent.set_left(self.right)
72
+ self.set_right(parent)
73
+ else
74
+ parent.set_right(self.left)
75
+ self.set_left(parent)
76
+ end
77
+ end
78
+
79
+ def zigzig?
80
+ (self.object_id == parent.left.object_id && parent.object_id == gparent.left.object_id) ||
81
+ (self.object_id == parent.right.object_id && parent.object_id == gparent.right.object_id)
82
+ end
83
+
84
+ def to_s
85
+ key.to_s
86
+ end
87
+
88
+ def to_h
89
+ { key => value }
90
+ end
91
+ alias_method :to_hash, :to_h
92
+
93
+ def to_a
94
+ [key, value]
95
+ end
96
+
97
+ def <=>(node)
98
+ return unless node
99
+ self.key <=> node.key
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,3 @@
1
+ class Splaytree
2
+ VERSION = "0.1.0"
3
+ end
data/lib/splaytree.rb ADDED
@@ -0,0 +1,271 @@
1
+ require 'splaytree/version'
2
+ require 'splaytree/node'
3
+
4
+ class Splaytree
5
+ include Enumerable
6
+
7
+ attr_reader :root
8
+
9
+ def initialize
10
+ @root = nil
11
+ @size = 0
12
+ end
13
+
14
+ def size
15
+ @size
16
+ end
17
+ alias_method :length, :size
18
+
19
+ def empty?
20
+ @root.nil?
21
+ end
22
+
23
+ def has_key?(key)
24
+ !!get(key)
25
+ end
26
+
27
+ def higher(key)
28
+ return if empty?
29
+ get(key)
30
+ return @root.to_h if @root.key > key
31
+ get_one_higher_of_root
32
+ end
33
+
34
+ def lower(key)
35
+ return if empty?
36
+ get(key)
37
+ return @root.to_h if @root.key < key
38
+ get_one_lower_of_root
39
+ end
40
+
41
+ def ceiling(key)
42
+ return if empty?
43
+ get(key)
44
+ return @root.to_h if @root.key >= key
45
+ get_one_higher_of_root
46
+ end
47
+
48
+ def floor(key)
49
+ return if empty?
50
+ get(key)
51
+ return @root.to_h if @root.key <= key
52
+ get_one_lower_of_root
53
+ end
54
+
55
+ def min
56
+ return if empty?
57
+ node = @root
58
+ while node.left
59
+ node = node.left
60
+ end
61
+ splay(node)
62
+ node.to_h
63
+ end
64
+
65
+ def max
66
+ return if empty?
67
+ node = @root
68
+ while node.right
69
+ node = node.right
70
+ end
71
+ splay(node)
72
+ node.to_h
73
+ end
74
+
75
+ def height
76
+ height_recursive(@root)
77
+ end
78
+
79
+ def get_with_duplicates(key)
80
+ return if empty?
81
+ get(key)
82
+ return if @root.key != key
83
+ @root.duplicates + [@root.value]
84
+ end
85
+
86
+ def get(key)
87
+ return if empty?
88
+ node = @root
89
+ value = nil
90
+ loop do
91
+ case key <=> node.key
92
+ when 0
93
+ value = node.value
94
+ break
95
+ when -1
96
+ break if node.left.nil?
97
+ node = node.left
98
+ when 1
99
+ break if node.right.nil?
100
+ node = node.right
101
+ else
102
+ fail
103
+ end
104
+ end
105
+ splay(node)
106
+ value
107
+ end
108
+ alias_method :[], :get
109
+
110
+ def insert(key, value)
111
+ node = Node.new(key, value)
112
+ if @root
113
+ current = @root
114
+ loop do
115
+ case key <=> current.key
116
+ when 0
117
+ node = current
118
+ node.add_duplicate!(value)
119
+ break
120
+ when -1
121
+ if !current.left
122
+ current.set_left(node)
123
+ break
124
+ end
125
+ current = current.left
126
+ when 1
127
+ if !current.right
128
+ current.set_right(node)
129
+ break
130
+ end
131
+ current = current.right
132
+ else
133
+ fail
134
+ end
135
+ end
136
+ end
137
+ splay(node)
138
+ @size += 1
139
+ return true
140
+ end
141
+ alias_method :[]=, :insert
142
+
143
+ def update(key, value)
144
+ return false if empty?
145
+ get(key)
146
+ return false if @root.key != key
147
+ @root.value = value
148
+ return true
149
+ end
150
+
151
+ def remove(key)
152
+ return if empty?
153
+ get(key)
154
+ return if @root.key != key
155
+ if @root.has_duplicates?
156
+ deleted = @root.remove_duplicate!
157
+ else
158
+ deleted = @root.value
159
+ if @root.left.nil?
160
+ @root = @root.right
161
+ @root.parent = nil
162
+ else
163
+ right = @root.right
164
+ @root = @root.left
165
+ @root.parent = nil
166
+ get(key)
167
+ @root.set_right(right)
168
+ end
169
+ end
170
+ @size -= 1
171
+ deleted
172
+ end
173
+
174
+ def clear
175
+ @root = nil
176
+ @size = 0
177
+ end
178
+
179
+ def each
180
+ return if self.empty?
181
+ stack = []
182
+ node = @root
183
+ loop do
184
+ if node
185
+ stack.push(node)
186
+ node.duplicates.each do |value|
187
+ stack.push(Node.new(node.key, value, node))
188
+ end
189
+ node = node.left
190
+ else
191
+ break if stack.empty?
192
+ node = stack.pop
193
+ yield(node)
194
+ node = node.right
195
+ end
196
+ end
197
+ end
198
+
199
+ def each_key(&block)
200
+ each { |node| yield node.key }
201
+ end
202
+
203
+ def each_value(&block)
204
+ each { |node| yield node.value }
205
+ end
206
+
207
+ def keys
208
+ to_enum(:each_key).to_a
209
+ end
210
+
211
+ def values
212
+ to_enum(:each_value).to_a
213
+ end
214
+
215
+ def report
216
+ return if empty?
217
+ result = []
218
+ each_with_index do |node, index|
219
+ result << { node: node.key, parent: node.parent&.key, left: node.left&.key, right: node.right&.key }
220
+ end
221
+ result
222
+ end
223
+
224
+ private
225
+
226
+ def get_one_higher_of_root
227
+ return if @root.right.nil?
228
+ node = @root.right
229
+ while node.left do
230
+ if node.left
231
+ node = node.left
232
+ end
233
+ end
234
+ splay(node)
235
+ node.to_h
236
+ end
237
+
238
+ def get_one_lower_of_root
239
+ return if @root.left.nil?
240
+ node = @root.left
241
+ while node.right do
242
+ node = node.right
243
+ end
244
+ splay(node)
245
+ node.to_h
246
+ end
247
+
248
+ def height_recursive(node)
249
+ return 0 unless node
250
+
251
+ left_height = 1 + height_recursive(node.left)
252
+ right_height = 1 + height_recursive(node.right)
253
+ left_height > right_height ? left_height : right_height
254
+ end
255
+
256
+ def splay(node)
257
+ while !node.root? do
258
+ parent = node.parent
259
+ if parent.root?
260
+ node.rotate
261
+ elsif node.zigzig?
262
+ parent.rotate
263
+ node.rotate
264
+ else
265
+ node.rotate
266
+ node.rotate
267
+ end
268
+ end
269
+ @root = node
270
+ end
271
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: splaytree
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Artur Babagulyyev
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-05-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.10'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.10'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest-reporters
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.1'
83
+ description: A splay tree is a self-adjusting binary search tree with the additional
84
+ property that recently accessed elements are quick to access again. It performs
85
+ basic operations such as insertion, look-up and removal in O(log n) amortized time.
86
+ email:
87
+ - artur.babagulyyev@gmail.com
88
+ executables: []
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - lib/splaytree.rb
93
+ - lib/splaytree/node.rb
94
+ - lib/splaytree/version.rb
95
+ homepage: https://github.com/SnowDiamond/splaytree
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.6.8
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Splay Tree Data Structure
119
+ test_files: []