splaytree 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []