splay_tree 0.3.0 → 0.4.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 +4 -4
- data/CHANGELOG.md +7 -0
- data/LICENSE.txt +1 -1
- data/README.md +54 -38
- data/lib/splay_tree.rb +9 -4
- data/lib/splay_tree/node.rb +8 -8
- data/lib/splay_tree/version.rb +1 -1
- metadata +20 -41
- data/Rakefile +0 -6
- data/benchmarks/speed.rb +0 -41
- data/spec/spec_helper.rb +0 -45
- data/spec/unit/default_spec.rb +0 -28
- data/spec/unit/delete_spec.rb +0 -43
- data/spec/unit/each_spec.rb +0 -55
- data/spec/unit/fetch_spec.rb +0 -56
- data/spec/unit/insert_spec.rb +0 -79
- data/spec/unit/new_spec.rb +0 -49
- data/spec/unit/to_hash_spec.rb +0 -12
- data/splay_tree.gemspec +0 -25
- data/tasks/console.rake +0 -10
- data/tasks/coverage.rake +0 -11
- data/tasks/spec.rake +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed0680c1501171f807509e9967af1a0f1cc34d5126ec8d72e2cdbc72da87df7f
|
4
|
+
data.tar.gz: 15fb0c87e206c6c0898ce1af4b45bd30ef94433b749ce5a118cee01ef4a85e4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1ca27ad3a3864f4b980deb35040e0a303ce85a5c0e66c9e320bb0fb7f6ca7d2378a05fe16f34ccb9bc1a2b58cf5ab71a0a678b4aa7c0e03becbb7ec72db7a84
|
7
|
+
data.tar.gz: c4d3122df89f96c7fb288b78b08373ec81f275af98910ca5216936cab09387ba49a04e5f7f00d51871fc1551f3cc23f8d056a69ed34530e347373fea021e94e8
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## [v0.4.0] - 2021-03-29
|
4
|
+
|
5
|
+
### Changed
|
6
|
+
* Change gemspec to remove test and rake files to reduce gem size
|
7
|
+
* Change to remove bundler as a dev dependency and relax rspec upper constraint
|
8
|
+
|
3
9
|
## [v0.3.0] - 2019-02-26
|
4
10
|
|
5
11
|
* Change to limit to Ruby >= 2.0.0
|
@@ -16,6 +22,7 @@
|
|
16
22
|
|
17
23
|
* Initial implementation and release
|
18
24
|
|
25
|
+
[v0.4.0]: https://github.com/piotrmurach/splay_tree/compare/v0.3.0...v0.4.0
|
19
26
|
[v0.3.0]: https://github.com/piotrmurach/splay_tree/compare/v0.2.0...v0.3.0
|
20
27
|
[v0.2.0]: https://github.com/piotrmurach/splay_tree/compare/v0.1.0...v0.2.0
|
21
28
|
[v0.1.0]: https://github.com/piotrmurach/splay_tree/compare/v0.1.0
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
# SplayTree
|
2
2
|
|
3
3
|
[][gem]
|
4
|
-
[][gh_actions_ci]
|
5
5
|
[][appveyor]
|
6
6
|
[][codeclimate]
|
7
7
|
[][coverage]
|
8
8
|
[][inchpages]
|
9
9
|
|
10
10
|
[gem]: http://badge.fury.io/rb/splay_tree
|
11
|
-
[
|
11
|
+
[gh_actions_ci]: https://github.com/piotrmurach/splay_tree/actions?query=workflow%3ACI
|
12
12
|
[appveyor]: https://ci.appveyor.com/project/piotrmurach/splay-tree
|
13
13
|
[codeclimate]: https://codeclimate.com/github/piotrmurach/splay_tree/maintainability
|
14
14
|
[coverage]: https://coveralls.io/github/piotrmurach/splay_tree
|
15
15
|
[inchpages]: http://inch-ci.org/github/piotrmurach/splay_tree
|
16
16
|
|
17
|
-
>
|
17
|
+
> A self-balancing binary tree optimised for fast access to frequently used nodes. Useful for implementing caches and garbage collection algorithms.
|
18
18
|
|
19
19
|
## Features
|
20
20
|
|
21
|
-
* Familiar
|
21
|
+
* Familiar `Hash` like access
|
22
22
|
* Easy instantiation with default value
|
23
23
|
|
24
24
|
## Installation
|
@@ -26,7 +26,7 @@
|
|
26
26
|
Add this line to your application's Gemfile:
|
27
27
|
|
28
28
|
```ruby
|
29
|
-
gem
|
29
|
+
gem "splay_tree"
|
30
30
|
```
|
31
31
|
|
32
32
|
And then execute:
|
@@ -55,103 +55,115 @@ Or install it yourself as:
|
|
55
55
|
tree = SplayTree.new
|
56
56
|
tree[:foo] = :bar
|
57
57
|
|
58
|
-
tree[:foo]
|
59
|
-
tree.size
|
58
|
+
tree[:foo] # => :bar
|
59
|
+
tree.size # => 1
|
60
60
|
```
|
61
61
|
|
62
62
|
### 1.1 insert
|
63
63
|
|
64
|
-
|
64
|
+
To assign a value to a given key do the following:
|
65
65
|
|
66
66
|
```ruby
|
67
67
|
tree = SplayTree.new
|
68
|
-
tree[
|
69
|
-
tree[
|
68
|
+
tree[:foo] = 1
|
69
|
+
tree[:bar] = 2
|
70
70
|
```
|
71
71
|
|
72
|
-
Note:
|
72
|
+
Note: The inserted key will be subjected to splaying, which means the tree will be rearranged to help with quicker access on subsequent calls.
|
73
73
|
|
74
74
|
### 1.2 fetch
|
75
75
|
|
76
|
-
To retrieve a value
|
76
|
+
To retrieve a value at a given key do:
|
77
77
|
|
78
78
|
```ruby
|
79
79
|
tree = SplayTree.new
|
80
|
-
tree[
|
80
|
+
tree[:foo] # => nil
|
81
81
|
|
82
|
-
tree[
|
83
|
-
tree[
|
82
|
+
tree[:foo] = 1
|
83
|
+
tree[:foo] # => 1
|
84
84
|
```
|
85
85
|
|
86
86
|
Note: Frequently accessed keys will move nearer to the root where they can be accessed more quickly.
|
87
87
|
|
88
88
|
### 1.3 default
|
89
89
|
|
90
|
-
|
90
|
+
You can set a default value for a missing key. This can be done during initialization:
|
91
91
|
|
92
92
|
```ruby
|
93
93
|
tree = SplayTree.new
|
94
|
-
tree.default
|
94
|
+
tree.default # => UndefinedValue
|
95
95
|
|
96
|
-
tree = SplayTree.new(
|
97
|
-
tree.default
|
98
|
-
tree[
|
96
|
+
tree = SplayTree.new(1)
|
97
|
+
tree.default # => 1
|
98
|
+
tree[:foo] # => 1
|
99
99
|
```
|
100
100
|
|
101
|
-
|
101
|
+
Or using `default` method:
|
102
102
|
|
103
103
|
```ruby
|
104
104
|
tree = SplayTree.new
|
105
|
-
tree.
|
105
|
+
tree.default = 1
|
106
106
|
|
107
|
-
tree
|
108
|
-
|
109
|
-
|
107
|
+
tree[:foo] # => 1
|
108
|
+
```
|
109
|
+
|
110
|
+
You can also use a block to set the default value:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
tree = SplayTree.new
|
114
|
+
tree.default_proc # => nil
|
115
|
+
|
116
|
+
tree = SplayTree.new { 1 }
|
117
|
+
tree.default_proc # => #<Proc...>
|
118
|
+
tree[:foo] # => 1
|
110
119
|
```
|
111
120
|
|
112
121
|
### 1.4 delete
|
113
122
|
|
114
|
-
In order to remove an entry from
|
123
|
+
In order to remove an entry from a splay tree use `delete` method. If a key is not found, the default value is returned, otherwise `nil`.
|
115
124
|
|
116
125
|
```ruby
|
117
126
|
tree = SplayTree.new
|
118
|
-
tree[
|
119
|
-
tree.delete(
|
120
|
-
tree.delete(
|
127
|
+
tree[:foo] = 1
|
128
|
+
tree.delete(:foo) # => 1
|
129
|
+
tree.delete(:bar) # => nil
|
121
130
|
```
|
122
131
|
|
123
132
|
### 1.5 empty?
|
124
133
|
|
125
|
-
|
134
|
+
Use `empty?` to check if a tree contains any elements:
|
126
135
|
|
127
136
|
```ruby
|
128
137
|
tree = SplayTree.new
|
129
|
-
tree.empty?
|
138
|
+
tree.empty? # => true
|
130
139
|
|
131
|
-
tree[
|
132
|
-
tree.empty?
|
140
|
+
tree[:foo] = 1
|
141
|
+
tree.empty? # => false
|
133
142
|
```
|
134
143
|
|
135
144
|
### 1.6 each
|
136
145
|
|
137
|
-
|
146
|
+
Use `each` method to iterate over all tree nodes like so:
|
138
147
|
|
139
148
|
```ruby
|
140
149
|
tree = SplayTree.new
|
141
|
-
tree[
|
142
|
-
tree[
|
150
|
+
tree[:foo] = 1
|
151
|
+
tree[:bar] = 2
|
143
152
|
|
144
153
|
tree.each { |key, value| puts "#{key}: #{value}" }
|
154
|
+
# =>
|
155
|
+
# bar: 2
|
156
|
+
# foo: 1
|
145
157
|
```
|
146
158
|
|
147
|
-
|
159
|
+
You can also use `each_key` and `each_value` to enumerate only keys or values:
|
148
160
|
|
149
161
|
```ruby
|
150
162
|
tree.each_key { |key| ... }
|
151
163
|
tree.each_value { |value| ... }
|
152
164
|
```
|
153
165
|
|
154
|
-
If no block is
|
166
|
+
If no block is given, an enumerator is returned instead.
|
155
167
|
|
156
168
|
## Contributing
|
157
169
|
|
@@ -161,6 +173,10 @@ If no block is provided, an enumerator is returned instead.
|
|
161
173
|
4. Push to the branch (`git push origin my-new-feature`)
|
162
174
|
5. Create a new Pull Request
|
163
175
|
|
176
|
+
## Code of Conduct
|
177
|
+
|
178
|
+
Everyone interacting in the SplayTree project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/piotrmurach/splay_tree/blob/master/CODE_OF_CONDUCT.md).
|
179
|
+
|
164
180
|
## Copyright
|
165
181
|
|
166
182
|
Copyright (c) 2014 Piotr Murach. See LICENSE for further details.
|
data/lib/splay_tree.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
3
|
+
require_relative "splay_tree/node"
|
4
|
+
require_relative "splay_tree/version"
|
5
5
|
|
6
6
|
class SplayTree
|
7
7
|
include Enumerable
|
@@ -195,8 +195,10 @@ class SplayTree
|
|
195
195
|
# @api public
|
196
196
|
def delete(key)
|
197
197
|
return if empty?
|
198
|
+
|
198
199
|
splay(key)
|
199
200
|
return if @root.key != key
|
201
|
+
|
200
202
|
deleted = @root
|
201
203
|
right = @root.right
|
202
204
|
@root = @root.left
|
@@ -226,7 +228,7 @@ class SplayTree
|
|
226
228
|
#
|
227
229
|
# @api public
|
228
230
|
def dump
|
229
|
-
@root.dump ||
|
231
|
+
@root.dump || ""
|
230
232
|
end
|
231
233
|
|
232
234
|
# Export tree as hash
|
@@ -235,7 +237,7 @@ class SplayTree
|
|
235
237
|
#
|
236
238
|
# @api public
|
237
239
|
def to_hash
|
238
|
-
|
240
|
+
each_with_object({}) { |(k, v), acc| acc[k] = v }
|
239
241
|
end
|
240
242
|
|
241
243
|
private
|
@@ -261,8 +263,10 @@ class SplayTree
|
|
261
263
|
@subtree.left = @subtree.right = Node::EMPTY
|
262
264
|
loop do
|
263
265
|
break if key == current.key
|
266
|
+
|
264
267
|
if key < current.key
|
265
268
|
break if current.left.empty?
|
269
|
+
|
266
270
|
if key < current.left.key
|
267
271
|
current = current.rotate_right
|
268
272
|
break if current.left.empty?
|
@@ -272,6 +276,7 @@ class SplayTree
|
|
272
276
|
current = current.left
|
273
277
|
elsif key > current.key
|
274
278
|
break if current.right.empty?
|
279
|
+
|
275
280
|
if key > current.right.key
|
276
281
|
current = current.rotate_left
|
277
282
|
break if current.right.empty?
|
data/lib/splay_tree/node.rb
CHANGED
@@ -55,15 +55,15 @@ class SplayTree
|
|
55
55
|
# Iterate over subtree nodes
|
56
56
|
#
|
57
57
|
# @api private
|
58
|
-
def each_key
|
59
|
-
each { |k,
|
58
|
+
def each_key
|
59
|
+
each { |k, _| yield k }
|
60
60
|
end
|
61
61
|
|
62
62
|
# Iterate over subtree nodes
|
63
63
|
#
|
64
64
|
# @api private
|
65
|
-
def each_value
|
66
|
-
each { |
|
65
|
+
def each_value
|
66
|
+
each { |_, v| yield v }
|
67
67
|
end
|
68
68
|
|
69
69
|
# Dump the subtree structure starting from this node
|
@@ -75,9 +75,9 @@ class SplayTree
|
|
75
75
|
left = @left.dump
|
76
76
|
right = @right.dump
|
77
77
|
if !@left.empty? || !@right.empty?
|
78
|
-
|
78
|
+
"(" + [@key, left || "-", right || "-"].compact.join(" ") + ")"
|
79
79
|
else
|
80
|
-
@key ||
|
80
|
+
@key || ""
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
@@ -128,12 +128,12 @@ class SplayTree
|
|
128
128
|
@right = @right.insert(key, value)
|
129
129
|
rotate_left
|
130
130
|
else
|
131
|
-
|
131
|
+
raise TypeError, "Cannot compare: #{key} with #{@key}"
|
132
132
|
end
|
133
133
|
end
|
134
134
|
|
135
135
|
class EmptyNode < Node
|
136
|
-
def initialize
|
136
|
+
def initialize(*)
|
137
137
|
end
|
138
138
|
|
139
139
|
def empty?
|
data/lib/splay_tree/version.rb
CHANGED
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: splay_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Murach
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-29 00:00:00.000000000 Z
|
12
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.5'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '1.5'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: rake
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -42,49 +28,42 @@ dependencies:
|
|
42
28
|
name: rspec
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
44
30
|
requirements:
|
45
|
-
- - "
|
31
|
+
- - ">="
|
46
32
|
- !ruby/object:Gem::Version
|
47
33
|
version: '3.0'
|
48
34
|
type: :development
|
49
35
|
prerelease: false
|
50
36
|
version_requirements: !ruby/object:Gem::Requirement
|
51
37
|
requirements:
|
52
|
-
- - "
|
38
|
+
- - ">="
|
53
39
|
- !ruby/object:Gem::Version
|
54
40
|
version: '3.0'
|
55
|
-
description:
|
56
|
-
|
57
|
-
algorithms.
|
41
|
+
description: A self-balancing binary tree optimised for fast access to frequently
|
42
|
+
used nodes. Useful for implementing caches and garbage collection algorithms.
|
58
43
|
email:
|
59
|
-
-
|
44
|
+
- piotr@piotrmurach.com
|
60
45
|
executables: []
|
61
46
|
extensions: []
|
62
|
-
extra_rdoc_files:
|
47
|
+
extra_rdoc_files:
|
48
|
+
- README.md
|
49
|
+
- CHANGELOG.md
|
50
|
+
- LICENSE.txt
|
63
51
|
files:
|
64
52
|
- CHANGELOG.md
|
65
53
|
- LICENSE.txt
|
66
54
|
- README.md
|
67
|
-
- Rakefile
|
68
|
-
- benchmarks/speed.rb
|
69
55
|
- lib/splay_tree.rb
|
70
56
|
- lib/splay_tree/node.rb
|
71
57
|
- lib/splay_tree/version.rb
|
72
|
-
- spec/spec_helper.rb
|
73
|
-
- spec/unit/default_spec.rb
|
74
|
-
- spec/unit/delete_spec.rb
|
75
|
-
- spec/unit/each_spec.rb
|
76
|
-
- spec/unit/fetch_spec.rb
|
77
|
-
- spec/unit/insert_spec.rb
|
78
|
-
- spec/unit/new_spec.rb
|
79
|
-
- spec/unit/to_hash_spec.rb
|
80
|
-
- splay_tree.gemspec
|
81
|
-
- tasks/console.rake
|
82
|
-
- tasks/coverage.rake
|
83
|
-
- tasks/spec.rake
|
84
58
|
homepage: https://github.com/piotrmurach/splay_tree
|
85
59
|
licenses:
|
86
60
|
- MIT
|
87
|
-
metadata:
|
61
|
+
metadata:
|
62
|
+
bug_tracker_uri: https://github.com/piotrmurach/splay_tree/issues
|
63
|
+
changelog_uri: https://github.com/piotrmurach/splay_tree/blob/master/CHANGELOG.md
|
64
|
+
documentation_uri: https://www.rubydoc.info/gems/splay_tree
|
65
|
+
homepage_uri: https://github.com/piotrmurach/splay_tree
|
66
|
+
source_code_uri: https://github.com/piotrmurach/splay_tree
|
88
67
|
post_install_message:
|
89
68
|
rdoc_options: []
|
90
69
|
require_paths:
|
@@ -100,9 +79,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
79
|
- !ruby/object:Gem::Version
|
101
80
|
version: '0'
|
102
81
|
requirements: []
|
103
|
-
|
104
|
-
rubygems_version: 2.7.3
|
82
|
+
rubygems_version: 3.1.2
|
105
83
|
signing_key:
|
106
84
|
specification_version: 4
|
107
|
-
summary: A self-balancing binary tree
|
85
|
+
summary: A self-balancing binary tree optimised for fast access to frequently used
|
86
|
+
nodes.
|
108
87
|
test_files: []
|
data/Rakefile
DELETED
data/benchmarks/speed.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'benchmark/ips'
|
4
|
-
require 'securerandom'
|
5
|
-
|
6
|
-
require_relative '../lib/splay_tree'
|
7
|
-
|
8
|
-
def generate_key(size)
|
9
|
-
SecureRandom.hex(size)
|
10
|
-
end
|
11
|
-
|
12
|
-
def insert_key(tree)
|
13
|
-
key = generate_key(10)
|
14
|
-
tree[key] = 1
|
15
|
-
key
|
16
|
-
end
|
17
|
-
|
18
|
-
def run(bench, object)
|
19
|
-
name = object.class.name
|
20
|
-
|
21
|
-
key = nil
|
22
|
-
|
23
|
-
bench.report("#{name} insert") do
|
24
|
-
key = insert_key(object)
|
25
|
-
end
|
26
|
-
|
27
|
-
bench.report("#{name} find") do
|
28
|
-
object[key]
|
29
|
-
end
|
30
|
-
|
31
|
-
bench.report("#{name} delete") do
|
32
|
-
object.delete(key)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
Benchmark.ips do |bench|
|
37
|
-
bench.config(time: 5, warmpu: 2)
|
38
|
-
|
39
|
-
run(bench, SplayTree.new)
|
40
|
-
run(bench, Hash.new)
|
41
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
if ENV['COVERAGE'] || ENV['TRAVIS']
|
4
|
-
require 'simplecov'
|
5
|
-
require 'coveralls'
|
6
|
-
|
7
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
8
|
-
SimpleCov::Formatter::HTMLFormatter,
|
9
|
-
Coveralls::SimpleCov::Formatter
|
10
|
-
]
|
11
|
-
|
12
|
-
SimpleCov.start do
|
13
|
-
command_name 'spec'
|
14
|
-
add_filter 'spec'
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
require 'splay_tree'
|
19
|
-
|
20
|
-
RSpec.configure do |config|
|
21
|
-
config.expect_with :rspec do |expectations|
|
22
|
-
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
23
|
-
end
|
24
|
-
|
25
|
-
config.mock_with :rspec do |mocks|
|
26
|
-
mocks.verify_partial_doubles = true
|
27
|
-
end
|
28
|
-
|
29
|
-
# Limits the available syntax to the non-monkey patched syntax that is recommended.
|
30
|
-
config.disable_monkey_patching!
|
31
|
-
|
32
|
-
# This setting enables warnings. It's recommended, but in some cases may
|
33
|
-
# be too noisy due to issues in dependencies.
|
34
|
-
config.warnings = true
|
35
|
-
|
36
|
-
if config.files_to_run.one?
|
37
|
-
config.default_formatter = 'doc'
|
38
|
-
end
|
39
|
-
|
40
|
-
config.profile_examples = 2
|
41
|
-
|
42
|
-
config.order = :random
|
43
|
-
|
44
|
-
Kernel.srand config.seed
|
45
|
-
end
|
data/spec/unit/default_spec.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe SplayTree, '.default' do
|
6
|
-
it "sets the default value on initialize" do
|
7
|
-
tree = SplayTree.new('foo')
|
8
|
-
expect(tree.default).to eq('foo')
|
9
|
-
expect(tree['a']).to eq('foo')
|
10
|
-
expect(tree.default_proc).to eq(nil)
|
11
|
-
end
|
12
|
-
|
13
|
-
it "sets the default value on assigment" do
|
14
|
-
tree = SplayTree.new
|
15
|
-
tree.default = 'foo'
|
16
|
-
expect(tree.default).to eq('foo')
|
17
|
-
expect(tree['a']).to eq('foo')
|
18
|
-
expect(tree.default_proc).to eq(nil)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "sets the default_proc to be executed on each key lookup" do
|
22
|
-
block = -> { 'foo' }
|
23
|
-
tree = SplayTree.new(&block)
|
24
|
-
expect(tree.default).to eq(SplayTree::UndefinedValue)
|
25
|
-
expect(tree.default_proc).to eq(block)
|
26
|
-
expect(tree['a']).to eq('foo')
|
27
|
-
end
|
28
|
-
end
|
data/spec/unit/delete_spec.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe SplayTree, 'delete' do
|
6
|
-
it "removes element from the tree" do
|
7
|
-
tree = SplayTree.new
|
8
|
-
tree['a'] = 1
|
9
|
-
tree['ab'] = 2
|
10
|
-
tree['abc'] = 3
|
11
|
-
tree['abd'] = 4
|
12
|
-
tree['ac'] = 5
|
13
|
-
tree['b'] = 6
|
14
|
-
|
15
|
-
expect(tree.size).to eq(6)
|
16
|
-
expect(tree.dump).to eq('(b (ac (abd (abc (ab a -) -) -) -) -)')
|
17
|
-
expect(tree.delete('xxx')).to eq(nil)
|
18
|
-
|
19
|
-
expect(tree.delete('abd')).to eq(4)
|
20
|
-
expect(tree.dump).to eq('(abc (ab a -) (ac - b))')
|
21
|
-
expect(tree.size).to eq(5)
|
22
|
-
|
23
|
-
expect(tree.delete('ab')).to eq(2)
|
24
|
-
expect(tree.dump).to eq('(a - (abc - (ac - b)))')
|
25
|
-
expect(tree.size).to eq(4)
|
26
|
-
|
27
|
-
expect(tree.delete('a')).to eq(1)
|
28
|
-
expect(tree.dump).to eq('(abc - (ac - b))')
|
29
|
-
expect(tree.size).to eq(3)
|
30
|
-
|
31
|
-
expect(tree.delete('abc')).to eq(3)
|
32
|
-
expect(tree.dump).to eq('(ac - b)')
|
33
|
-
expect(tree.size).to eq(2)
|
34
|
-
|
35
|
-
expect(tree.delete('ac')).to eq(5)
|
36
|
-
expect(tree.dump).to eq('b')
|
37
|
-
expect(tree.size).to eq(1)
|
38
|
-
|
39
|
-
expect(tree.delete('b')).to eq(6)
|
40
|
-
expect(tree.dump).to eq('')
|
41
|
-
expect(tree.size).to eq(0)
|
42
|
-
end
|
43
|
-
end
|
data/spec/unit/each_spec.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe SplayTree, '.each' do
|
6
|
-
subject(:tree) { described_class.new }
|
7
|
-
|
8
|
-
before {
|
9
|
-
tree['a'] = 1
|
10
|
-
tree['b'] = 2
|
11
|
-
tree['c'] = 3
|
12
|
-
}
|
13
|
-
|
14
|
-
it "enumartes all pairs" do
|
15
|
-
yielded = []
|
16
|
-
expect {
|
17
|
-
tree.each { |k, v| yielded << [k, v] }
|
18
|
-
}.to change { yielded }.from([]).to([['a', 1], ['b', 2], ['c', 3]])
|
19
|
-
expect(tree.to_a).to eq(yielded)
|
20
|
-
end
|
21
|
-
|
22
|
-
it "returns enumerator for all pairs without block" do
|
23
|
-
expect(tree.each.to_a).to eq([['a', 1], ['b', 2], ['c', 3]])
|
24
|
-
end
|
25
|
-
|
26
|
-
it "enumerates all keys" do
|
27
|
-
yielded = []
|
28
|
-
expect {
|
29
|
-
tree.each_key { |k| yielded << k }
|
30
|
-
}.to change { yielded }.from([]).to(['a', 'b', 'c'])
|
31
|
-
end
|
32
|
-
|
33
|
-
it "returns enumerator for all keys without block" do
|
34
|
-
expect(tree.each_key.to_a).to eq(['a', 'b', 'c'])
|
35
|
-
end
|
36
|
-
|
37
|
-
it "enumerates all values" do
|
38
|
-
yielded = []
|
39
|
-
expect {
|
40
|
-
tree.each_value { |v| yielded << v }
|
41
|
-
}.to change { yielded }.from([]).to([1, 2, 3])
|
42
|
-
end
|
43
|
-
|
44
|
-
it "returns enumerator for all values without block" do
|
45
|
-
expect(tree.each_value.to_a).to eq([1, 2, 3])
|
46
|
-
end
|
47
|
-
|
48
|
-
it "populates all keys" do
|
49
|
-
expect(tree.keys).to eq(['a', 'b', 'c'])
|
50
|
-
end
|
51
|
-
|
52
|
-
it "populates all values" do
|
53
|
-
expect(tree.values).to eq([1, 2, 3])
|
54
|
-
end
|
55
|
-
end
|
data/spec/unit/fetch_spec.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe SplayTree, 'fetch' do
|
6
|
-
it "removes element from the tree" do
|
7
|
-
tree = SplayTree.new
|
8
|
-
tree['aa'] = 1
|
9
|
-
tree['ab'] = 2
|
10
|
-
tree['bb'] = 3
|
11
|
-
tree['bc'] = 4
|
12
|
-
tree['a'] = 5
|
13
|
-
tree['abc'] = 6
|
14
|
-
|
15
|
-
expect(tree.size).to eq(6)
|
16
|
-
expect(tree.dump).to eq('(abc (a - (ab aa -)) (bc bb -))')
|
17
|
-
|
18
|
-
expect(tree.delete('abc')).to eq(6)
|
19
|
-
expect(tree.dump).to eq('(ab (a - aa) (bc bb -))')
|
20
|
-
expect(tree['aa']).to eq(1)
|
21
|
-
expect(tree['ab']).to eq(2)
|
22
|
-
expect(tree['bb']).to eq(3)
|
23
|
-
expect(tree['bc']).to eq(4)
|
24
|
-
expect(tree['a']).to eq(5)
|
25
|
-
expect(tree['abc']).to eq(nil)
|
26
|
-
|
27
|
-
expect(tree.delete('ab')).to eq(2)
|
28
|
-
expect(tree.dump).to eq('(aa a (bb - bc))')
|
29
|
-
expect(tree['aa']).to eq(1)
|
30
|
-
expect(tree['ab']).to eq(nil)
|
31
|
-
expect(tree['bb']).to eq(3)
|
32
|
-
expect(tree['bc']).to eq(4)
|
33
|
-
expect(tree['a']).to eq(5)
|
34
|
-
expect(tree['abc']).to eq(nil)
|
35
|
-
end
|
36
|
-
|
37
|
-
it "checks for key existance" do
|
38
|
-
tree = SplayTree.new
|
39
|
-
tree['a'] = 1
|
40
|
-
expect(tree.key?('a')).to eq(true)
|
41
|
-
end
|
42
|
-
|
43
|
-
it "accepts keys with comparison operator" do
|
44
|
-
tree = SplayTree.new
|
45
|
-
obj = Module.new
|
46
|
-
tree['a'] = 1
|
47
|
-
expect { tree[obj] = 2 }.to raise_error(TypeError)
|
48
|
-
end
|
49
|
-
|
50
|
-
it "bla" do
|
51
|
-
tree = SplayTree.new
|
52
|
-
tree['a'] = 1
|
53
|
-
tree['b'] = 2
|
54
|
-
expect(tree['x']).to eq(nil)
|
55
|
-
end
|
56
|
-
end
|
data/spec/unit/insert_spec.rb
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe SplayTree, 'insert' do
|
6
|
-
it "overrides existing value" do
|
7
|
-
tree = described_class.new
|
8
|
-
tree['a'] = 1
|
9
|
-
tree['a'] = 2
|
10
|
-
expect(tree.size).to eq(1)
|
11
|
-
expect(tree['a']).to eq(2)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "balances out the leaves" do
|
15
|
-
tree = described_class.new
|
16
|
-
tree['a'] = 1
|
17
|
-
tree['b'] = 2
|
18
|
-
tree['c'] = 3
|
19
|
-
tree['d'] = 4
|
20
|
-
tree['e'] = 5
|
21
|
-
expect(tree.dump).to eq('(e (d (c (b a -) -) -) -)')
|
22
|
-
expect(tree['c']).to eq(3)
|
23
|
-
expect(tree.dump).to eq('(c (b a -) (d - e))')
|
24
|
-
end
|
25
|
-
|
26
|
-
it "inserts items to the left" do
|
27
|
-
tree = described_class.new
|
28
|
-
tree['c'] = 1
|
29
|
-
tree['b'] = 2
|
30
|
-
# zig right
|
31
|
-
expect(tree.dump).to eq('(b - c)')
|
32
|
-
tree['a'] = 3
|
33
|
-
# zig right
|
34
|
-
expect(tree.dump).to eq('(a - (b - c))')
|
35
|
-
end
|
36
|
-
|
37
|
-
it "inserts items to the right" do
|
38
|
-
tree = described_class.new
|
39
|
-
tree['a'] = 1
|
40
|
-
expect(tree.dump).to eq('a')
|
41
|
-
tree['b'] = 2
|
42
|
-
# zig left
|
43
|
-
expect(tree.dump).to eq('(b a -)')
|
44
|
-
tree['c'] = 3
|
45
|
-
# zig left
|
46
|
-
expect(tree.dump).to eq('(c (b a -) -)')
|
47
|
-
end
|
48
|
-
|
49
|
-
it "inserts to the left and the right" do
|
50
|
-
tree = described_class.new
|
51
|
-
expect(tree.dump).to eq('')
|
52
|
-
tree['g'] = 1
|
53
|
-
tree['a'] = 2
|
54
|
-
# zig right
|
55
|
-
expect(tree.dump).to eq('(a - g)')
|
56
|
-
tree['w'] = 3
|
57
|
-
expect(tree.dump).to eq('(w (a - g) -)')
|
58
|
-
# zig-zag right
|
59
|
-
tree['d'] = 4
|
60
|
-
expect(tree.dump).to eq('(d a (w g -))')
|
61
|
-
end
|
62
|
-
|
63
|
-
it "builds the tree correctly" do
|
64
|
-
tree = described_class.new
|
65
|
-
tree['b'] = 1
|
66
|
-
tree['a'] = 2
|
67
|
-
expect(tree.dump).to eq("(a - b)")
|
68
|
-
tree['e'] = 3
|
69
|
-
expect(tree.dump).to eq("(e (a - b) -)")
|
70
|
-
tree['f'] = 4
|
71
|
-
expect(tree.dump).to eq("(f (e (a - b) -) -)")
|
72
|
-
tree['g'] = 5
|
73
|
-
expect(tree.dump).to eq("(g (f (e (a - b) -) -) -)")
|
74
|
-
tree['i'] = 6
|
75
|
-
expect(tree.dump).to eq("(i (g (f (e (a - b) -) -) -) -)")
|
76
|
-
tree['d'] = 7
|
77
|
-
expect(tree.dump).to eq("(d (a - b) (i (g (f e -) -) -))")
|
78
|
-
end
|
79
|
-
end
|
data/spec/unit/new_spec.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe SplayTree, 'new' do
|
6
|
-
it "creates tree" do
|
7
|
-
tree = described_class.new
|
8
|
-
|
9
|
-
expect(tree.empty?).to be(true)
|
10
|
-
expect(tree.size).to eq(0)
|
11
|
-
expect(tree['a']).to eq(nil)
|
12
|
-
|
13
|
-
tree['a'] = 1
|
14
|
-
expect(tree.empty?).to be(false)
|
15
|
-
expect(tree.size).to eq(1)
|
16
|
-
expect(tree['a']).to eq(1)
|
17
|
-
expect(tree.dump).to eq('a')
|
18
|
-
|
19
|
-
tree['b'] = 2
|
20
|
-
expect(tree.size).to eq(2)
|
21
|
-
expect(tree.dump).to eq('(b a -)')
|
22
|
-
|
23
|
-
tree['c'] = 3
|
24
|
-
expect(tree.size).to eq(3)
|
25
|
-
expect(tree.dump).to eq('(c (b a -) -)')
|
26
|
-
|
27
|
-
tree['d'] = 4
|
28
|
-
expect(tree.size).to eq(4)
|
29
|
-
expect(tree.dump).to eq('(d (c (b a -) -) -)')
|
30
|
-
end
|
31
|
-
|
32
|
-
it "raises error when defualt and block given" do
|
33
|
-
expect {
|
34
|
-
SplayTree.new(0) { :unknown }
|
35
|
-
}.to raise_error(ArgumentError)
|
36
|
-
end
|
37
|
-
|
38
|
-
it "defaults to value" do
|
39
|
-
tree = SplayTree.new(0)
|
40
|
-
expect(tree['a']).to eq(0)
|
41
|
-
expect(tree['b']).to eq(0)
|
42
|
-
end
|
43
|
-
|
44
|
-
it "default to block" do
|
45
|
-
tree = SplayTree.new { ['a'] }
|
46
|
-
expect(tree[1]).to eq(['a'])
|
47
|
-
expect(tree[2]).to eq(['a'])
|
48
|
-
end
|
49
|
-
end
|
data/spec/unit/to_hash_spec.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe SplayTree, '.to_hash' do
|
6
|
-
it "exports tree as hash" do
|
7
|
-
tree = SplayTree.new
|
8
|
-
hash = {'a' => 1, 'ab' => 2, 'abc' => 3, 'abd' => 4, 'ac' => 5, 'b' => 6}
|
9
|
-
hash.each { |k, v| tree[k] = v }
|
10
|
-
expect(tree.to_hash).to eq(hash)
|
11
|
-
end
|
12
|
-
end
|
data/splay_tree.gemspec
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
lib = File.expand_path('../lib', __FILE__)
|
2
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require 'splay_tree/version'
|
4
|
-
|
5
|
-
Gem::Specification.new do |spec|
|
6
|
-
spec.name = "splay_tree"
|
7
|
-
spec.version = SplayTree::VERSION
|
8
|
-
spec.authors = ["Piotr Murach"]
|
9
|
-
spec.email = ["me@piotrmurach.com"]
|
10
|
-
spec.summary = %q{A self-balancing binary tree with amortized access.}
|
11
|
-
spec.description = %q{Self balancing binary tree that keeps lookup operations fast by optimizing frequently accessed keys. Useful for implementing caches and garbage collection algorithms.}
|
12
|
-
spec.homepage = "https://github.com/piotrmurach/splay_tree"
|
13
|
-
spec.license = "MIT"
|
14
|
-
|
15
|
-
spec.files = Dir['{lib,spec,benchmarks}/**/*.rb']
|
16
|
-
spec.files += Dir['tasks/*', 'splay_tree.gemspec']
|
17
|
-
spec.files += Dir['README.md', 'CHANGELOG.md', 'LICENSE.txt', 'Rakefile']
|
18
|
-
spec.require_paths = ["lib"]
|
19
|
-
|
20
|
-
spec.required_ruby_version = '>= 2.0.0'
|
21
|
-
|
22
|
-
spec.add_development_dependency "bundler", ">= 1.5"
|
23
|
-
spec.add_development_dependency "rake"
|
24
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
25
|
-
end
|
data/tasks/console.rake
DELETED
data/tasks/coverage.rake
DELETED
data/tasks/spec.rake
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
begin
|
4
|
-
require 'rspec/core/rake_task'
|
5
|
-
|
6
|
-
desc 'Run all specs'
|
7
|
-
RSpec::Core::RakeTask.new(:spec) do |task|
|
8
|
-
task.pattern = 'spec/{unit,integration}{,/*/**}/*_spec.rb'
|
9
|
-
end
|
10
|
-
|
11
|
-
namespace :spec do
|
12
|
-
desc 'Run unit specs'
|
13
|
-
RSpec::Core::RakeTask.new(:unit) do |task|
|
14
|
-
task.pattern = 'spec/unit{,/*/**}/*_spec.rb'
|
15
|
-
end
|
16
|
-
|
17
|
-
desc 'Run integration specs'
|
18
|
-
RSpec::Core::RakeTask.new(:integration) do |task|
|
19
|
-
task.pattern = 'spec/integration{,/*/**}/*_spec.rb'
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
rescue LoadError
|
24
|
-
%w[spec spec:unit spec:integration].each do |name|
|
25
|
-
task name do
|
26
|
-
$stderr.puts "In order to run #{name}, do `gem install rspec`"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|