splay_tree 0.1.0 → 0.2.0

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