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 +7 -0
- data/lib/splaytree/node.rb +103 -0
- data/lib/splaytree/version.rb +3 -0
- data/lib/splaytree.rb +271 -0
- metadata +119 -0
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
|
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: []
|