splay_tree 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3fb742e0b556b47b38822511385221c6b753f7ff
4
- data.tar.gz: 3b4815cae5de148ff8ca12b8b780ad3713d2a406
3
+ metadata.gz: c66b504221015b64dc0e1ea92bfe583eb279a9e3
4
+ data.tar.gz: d7a06439164029d713e38135ffff5786435675aa
5
5
  SHA512:
6
- metadata.gz: 202309dfa438b35db3e859167679a8bba623ac1f0d50c94ba0d335b05a75421d2978567991646dc637a7fa0bfabdd1b07af3d66d1f9952c7e352635a81c270cd
7
- data.tar.gz: 88fa044eb915009af13333272c38c868c10fb2d915b25b0396eb61d20be19ca1ac0157d451ccbc6d09820906688ce4aec1cb4e63dff8399ea86a73edca932cdb
6
+ metadata.gz: 074fe40542d0b6665e01a8dc5a31b2efe7402676c5d7e78cb95a30da616e146cd83801d9f5a401cc76bf90cf7a29c2f1adf36f9c6b1c33a433aff3c720189ef7
7
+ data.tar.gz: 4f0d1375ef8aed9e1d30fc632a3fe1e44eb3f4765f4411314de5fd6eaf8e6df7a9fc896494ce16b3152a4d35f9901a64690c539189791b52c3dd57238797b64f
data/.travis.yml CHANGED
@@ -5,6 +5,7 @@ rvm:
5
5
  - 1.9.3
6
6
  - 2.0.0
7
7
  - 2.1.0
8
+ - 2.2.0
8
9
  - ruby-head
9
10
  matrix:
10
11
  include:
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ 0.2.0 (January 3, 2015)
2
+
3
+ * Add ability to set default through value and block
4
+ * Add ability to iterate over keys and values
5
+ * Add to_hash export
data/Gemfile CHANGED
@@ -7,6 +7,7 @@ group :development do
7
7
  gem 'rspec', '~> 3.1.0'
8
8
  gem 'yard', '~> 0.8.7'
9
9
  gem 'timecop', '~> 0.7.1'
10
+ gem 'benchmark-ips', '~> 2.0.0'
10
11
  end
11
12
 
12
13
  group :metrics do
data/README.md CHANGED
@@ -3,11 +3,13 @@
3
3
  [![Build Status](https://secure.travis-ci.org/peter-murach/splay_tree.png?branch=master)][travis]
4
4
  [![Code Climate](https://codeclimate.com/github/peter-murach/splay_tree.png)][codeclimate]
5
5
  [![Coverage Status](https://coveralls.io/repos/peter-murach/splay_tree/badge.png)][coverage]
6
+ [![Inline docs](http://inch-ci.org/github/peter-murach/splay_tree.png)][inchpages]
6
7
 
7
8
  [gem]: http://badge.fury.io/rb/splay_tree
8
9
  [travis]: http://travis-ci.org/peter-murach/splay_tree
9
10
  [codeclimate]: https://codeclimate.com/github/peter-murach/splay_tree
10
11
  [coverage]: https://coveralls.io/r/peter-murach/splay_tree
12
+ [inchpages]: http://inch-ci.org/github/peter-murach/splay_tree
11
13
 
12
14
  > Self balancing binary tree that keeps lookup operations fast by optimizing frequently accessed keys. Useful for implementing caches and garbage collection algorithms.
13
15
 
@@ -32,6 +34,16 @@ Or install it yourself as:
32
34
 
33
35
  $ gem install splay_tree
34
36
 
37
+ ## Contents
38
+
39
+ * [1. Usage](#1-usage)
40
+ * [1.1 insert](#11-insert)
41
+ * [1.2 fetch](#12-fetch)
42
+ * [1.3 default](#13-default)
43
+ * [1.4 delete](#14-delete)
44
+ * [1.5 empty?](#15-empty)
45
+ * [1.6 each](#16-each)
46
+
35
47
  ## 1. Usage
36
48
 
37
49
  **SplayTree** operations are similar to that of `Hash`:
@@ -46,28 +58,66 @@ tree.size # => 1
46
58
 
47
59
  ### 1.1 insert
48
60
 
49
- In order to add two elements:
61
+ In order to associate the value with the given key do:
50
62
 
51
63
  ```ruby
52
- tree['a'] = 1
53
- tree['b'] = 2
64
+ tree = SplayTree.new
65
+ tree["a"] = 1
66
+ tree["b"] = 2
54
67
  ```
55
68
 
69
+ Note: Inserted key will be subjected to splaying, which means the tree will be rearranged to help with quicker access on subsequent calls.
70
+
56
71
  ### 1.2 fetch
57
72
 
58
- To read value under key:
73
+ To retrieve a value from the tree corresponding to the key do:
74
+
75
+ ```ruby
76
+ tree = SplayTree.new
77
+ tree["a"] # => nil
78
+
79
+ tree["a"] = 1
80
+ tree["a"] # => 1
81
+ ```
82
+
83
+ Note: Frequently accessed keys will move nearer to the root where they can be accessed more quickly.
84
+
85
+ ### 1.3 default
86
+
87
+ **SplayTree** allows you to set default value if key does not exist. This can be done during initialization or using `default` method:
88
+
89
+ ```ruby
90
+ tree = SplayTree.new
91
+ tree.default # => UndefinedValue
92
+
93
+ tree = SplayTree.new("foo")
94
+ tree.default # => "foo"
95
+ tree["a"] # => "foo"
96
+ ```
97
+
98
+ You can also use block to set default value:
59
99
 
60
100
  ```ruby
61
- tree['a']
101
+ tree = SplayTree.new
102
+ tree.default_proc # => nil
103
+
104
+ tree = SplayTree.new { "foo" }
105
+ tree.default_proc # => "foo"
106
+ tree["a"] # => "foo"
62
107
  ```
63
108
 
64
- ### 1.3 delete
109
+ ### 1.4 delete
110
+
111
+ In order to remove an entry from the splay tree use `delete`. If the value is not found the default value is returned and `nil` otherwise.
65
112
 
66
113
  ```ruby
114
+ tree = SplayTree.new
115
+ tree['a'] = 1
67
116
  tree.delete('a') # => 1
117
+ tree.delete('z') # => nil
68
118
  ```
69
119
 
70
- ### 1.4 empty?
120
+ ### 1.5 empty?
71
121
 
72
122
  To check if `tree` contains any elements call `empty?` like so:
73
123
 
@@ -75,10 +125,31 @@ To check if `tree` contains any elements call `empty?` like so:
75
125
  tree = SplayTree.new
76
126
  tree.empty? # => true
77
127
 
78
- tree['a'] = 1
128
+ tree["a"] = 1
79
129
  tree.empty? # => false
80
130
  ```
81
131
 
132
+ ### 1.6 each
133
+
134
+ In order to iterate over all tree nodes use `each` method like so:
135
+
136
+ ```ruby
137
+ tree = SplayTree.new
138
+ tree['a'] = 1
139
+ tree['b'] = 2
140
+
141
+ tree.each { |key, value| puts "#{key}: #{value}" }
142
+ ```
143
+
144
+ In addition you can use `each_key`, `each_value` to enumerate only keys and values respectively.
145
+
146
+ ```ruby
147
+ tree.each_key { |key| ... }
148
+ tree.each_value { |value| ... }
149
+ ```
150
+
151
+ If no block is provided, an enumerator is returned instead.
152
+
82
153
  ## Contributing
83
154
 
84
155
  1. Fork it ( https://github.com/peter-murach/splay_tree/fork )
@@ -89,4 +160,4 @@ tree.empty? # => false
89
160
 
90
161
  ## Copyright
91
162
 
92
- Copyright (c) 2014 Piotr Murach. See LICENSE for further details.
163
+ Copyright (c) 2014-2015 Piotr Murach. See LICENSE for further details.
@@ -0,0 +1,40 @@
1
+ # coding: utf-8
2
+
3
+ require 'benchmark/ips'
4
+ require 'splay_tree'
5
+ require 'securerandom'
6
+
7
+ def generate_key(size)
8
+ SecureRandom.hex(size)
9
+ end
10
+
11
+ def insert_key(tree)
12
+ key = generate_key(10)
13
+ tree[key] = 1
14
+ key
15
+ end
16
+
17
+ def run(bench, object)
18
+ name = object.class.name
19
+
20
+ key = nil
21
+
22
+ bench.report("#{name} insert") do
23
+ key = insert_key(object)
24
+ end
25
+
26
+ bench.report("#{name} find") do
27
+ object[key]
28
+ end
29
+
30
+ bench.report("#{name} delete") do
31
+ object.delete(key)
32
+ end
33
+ end
34
+
35
+ Benchmark.ips do |bench|
36
+ bench.config(time: 5, warmpu: 2)
37
+
38
+ run(bench, SplayTree.new)
39
+ run(bench, Hash.new)
40
+ end
@@ -43,6 +43,29 @@ class SplayTree
43
43
  @key <=> other.key
44
44
  end
45
45
 
46
+ # Iterate over subtree nodes
47
+ #
48
+ # @api private
49
+ def each(&block)
50
+ @left.each(&block)
51
+ yield [@key, @value]
52
+ @right.each(&block)
53
+ end
54
+
55
+ # Iterate over subtree nodes
56
+ #
57
+ # @api private
58
+ def each_key(&block)
59
+ each { |k, v| yield k }
60
+ end
61
+
62
+ # Iterate over subtree nodes
63
+ #
64
+ # @api private
65
+ def each_value(&block)
66
+ each { |k, v| yield v }
67
+ end
68
+
46
69
  # Dump the subtree structure starting from this node
47
70
  #
48
71
  # @return [String]
@@ -121,11 +144,11 @@ class SplayTree
121
144
  0
122
145
  end
123
146
 
124
- def to_s
125
- end
147
+ def to_s; end
126
148
 
127
- def dump
128
- end
149
+ def dump; end
150
+
151
+ def each(&block); end
129
152
 
130
153
  def insert(key, value)
131
154
  Node.new(key, value)
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
2
 
3
3
  class SplayTree
4
- VERSION = "0.1.0"
4
+ VERSION = '0.2.0'
5
5
  end # SplayTree
data/lib/splay_tree.rb CHANGED
@@ -4,10 +4,26 @@ require 'splay_tree/node'
4
4
  require 'splay_tree/version'
5
5
 
6
6
  class SplayTree
7
+ include Enumerable
8
+
7
9
  UndefinedValue = Module.new
8
10
 
11
+ # The default value for non existent key
12
+ #
13
+ # @api public
9
14
  attr_accessor :default
10
15
 
16
+ # The default block for non existent key
17
+ #
18
+ # @api public
19
+ attr_accessor :default_proc
20
+
21
+ # Create a SplayTree
22
+ #
23
+ # @param [Object] default
24
+ # the default value for missing key
25
+ #
26
+ # @api public
11
27
  def initialize(default = UndefinedValue, &block)
12
28
  if !UndefinedValue.equal?(default) && block
13
29
  fail ArgumentError,
@@ -16,7 +32,7 @@ class SplayTree
16
32
  @root = Node::EMPTY
17
33
  @subtree = Node.new(nil, nil)
18
34
  @default = default
19
- @default_block = block
35
+ @default_proc = block
20
36
  end
21
37
 
22
38
  # @api public
@@ -30,6 +46,91 @@ class SplayTree
30
46
  end
31
47
  alias_method :length, :size
32
48
 
49
+ # Iterate over each key & value pair in the tree
50
+ #
51
+ # @example
52
+ # tree = SplayTree.new
53
+ # tree.each { |key, val| ... }
54
+ #
55
+ # @yield [key, value]
56
+ #
57
+ # @yieldparam [Object] key
58
+ # @yieldparam [Object] value
59
+ #
60
+ # @return [self]
61
+ #
62
+ # @api public
63
+ def each(&block)
64
+ if block_given?
65
+ @root.each(&block)
66
+ self
67
+ else
68
+ @root.to_enum
69
+ end
70
+ end
71
+
72
+ # Iterate over each key in the tree
73
+ #
74
+ # @example
75
+ # tree = SplayTree.new
76
+ # tree.each_key { |key| ... }
77
+ #
78
+ # @yield [key]
79
+ #
80
+ # @yieldparam [Object] key
81
+ #
82
+ # @return [self]
83
+ #
84
+ # @api public
85
+ def each_key(&block)
86
+ if block_given?
87
+ @root.each_key(&block)
88
+ self
89
+ else
90
+ @root.to_enum(:each_key)
91
+ end
92
+ end
93
+
94
+ # Iterate over each value in the tree
95
+ #
96
+ # @example
97
+ # tree = SplayTree.new
98
+ # tree.each_value { |val| ... }
99
+ #
100
+ # @yield [value]
101
+ #
102
+ # @yieldparam [Object] value
103
+ #
104
+ # @return [self]
105
+ #
106
+ # @api public
107
+ def each_value(&block)
108
+ if block_given?
109
+ @root.each_value(&block)
110
+ self
111
+ else
112
+ @root.to_enum(:each_value)
113
+ end
114
+ end
115
+
116
+ # Return a new array of all the keys in the tree
117
+ #
118
+ # @return [Array[Object]]
119
+ #
120
+ # @api public
121
+ def keys
122
+ each_key.to_a
123
+ end
124
+
125
+ # Return a new array of all the values in the tree
126
+ #
127
+ # @return [Array[Object]]
128
+ #
129
+ # @api public
130
+ def values
131
+ each_value.to_a
132
+ end
133
+
33
134
  # Insert a node into a tree with the given key and value
34
135
  # provided that the tree does not already contain the key.
35
136
  # The node becomes the root of the tree.
@@ -127,14 +228,23 @@ class SplayTree
127
228
  @root.dump || ''
128
229
  end
129
230
 
231
+ # Export tree as hash
232
+ #
233
+ # @return [Hash]
234
+ #
235
+ # @api public
236
+ def to_hash
237
+ reduce({}) { |acc, (k, v)| acc[k] = v; acc }
238
+ end
239
+
130
240
  private
131
241
 
132
242
  # @api private
133
243
  def default_value
134
244
  if @default != UndefinedValue
135
245
  @default
136
- elsif @default_block
137
- @default_block.call
246
+ elsif @default_proc
247
+ @default_proc.call
138
248
  end
139
249
  end
140
250
 
@@ -0,0 +1,28 @@
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
@@ -0,0 +1,55 @@
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
@@ -0,0 +1,12 @@
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
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: splay_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.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: 2014-12-27 00:00:00.000000000 Z
11
+ date: 2015-01-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -37,18 +37,23 @@ files:
37
37
  - .rspec
38
38
  - .ruby-version
39
39
  - .travis.yml
40
+ - CHANGELOG.md
40
41
  - Gemfile
41
42
  - LICENSE.txt
42
43
  - README.md
43
44
  - Rakefile
45
+ - benchmarks/speed.rb
44
46
  - lib/splay_tree.rb
45
47
  - lib/splay_tree/node.rb
46
48
  - lib/splay_tree/version.rb
47
49
  - spec/spec_helper.rb
50
+ - spec/unit/default_spec.rb
48
51
  - spec/unit/delete_spec.rb
52
+ - spec/unit/each_spec.rb
49
53
  - spec/unit/fetch_spec.rb
50
54
  - spec/unit/insert_spec.rb
51
55
  - spec/unit/new_spec.rb
56
+ - spec/unit/to_hash_spec.rb
52
57
  - splay_tree.gemspec
53
58
  - tasks/console.rake
54
59
  - tasks/coverage.rake
@@ -79,8 +84,11 @@ specification_version: 4
79
84
  summary: A self-balancing binary tree with amortized access.
80
85
  test_files:
81
86
  - spec/spec_helper.rb
87
+ - spec/unit/default_spec.rb
82
88
  - spec/unit/delete_spec.rb
89
+ - spec/unit/each_spec.rb
83
90
  - spec/unit/fetch_spec.rb
84
91
  - spec/unit/insert_spec.rb
85
92
  - spec/unit/new_spec.rb
93
+ - spec/unit/to_hash_spec.rb
86
94
  has_rdoc: