tree-red_black 0.4.2
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/.gitignore +12 -0
- data/.travis.yml +10 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +36 -0
- data/LICENSE.txt +21 -0
- data/README.md +572 -0
- data/Rakefile +12 -0
- data/contrib/iterate_dot_graphs.rb +208 -0
- data/lib/tree-red_black.rb +1 -0
- data/lib/tree/red_black.rb +243 -0
- data/lib/tree/red_black/red_black_node.rb +645 -0
- data/lib/tree/red_black/version.rb +6 -0
- data/tree-red_black.gemspec +31 -0
- metadata +122 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 01243ab97c7f5ed1ac6ff3dcb41b9e9c62bbfa709c348df9ba0c69c69b652974
|
4
|
+
data.tar.gz: 6109eec9ae6ec7d0de5f583d50588c7aa349efad76ab9b987ea857afc442ad2e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: df4e50125126871fb649f3316082fc38dd9fe472003411f5d50dca93d4ccd64fbb7dc537ba7a1df95448ad6342c157b95325946f29a88b918b7b5dfe4bea41d0
|
7
|
+
data.tar.gz: e8b85911d1606729def0deba609fca3316bd986c11dc837a75409d255176588c63fc4845b1db75aa1f0812509956dd11775c4fca09a454cd7722b82acfe9b616
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at TODO: Write your email address. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
tree-red_black (0.4.2)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.3)
|
10
|
+
rake (13.0.1)
|
11
|
+
rspec (3.9.0)
|
12
|
+
rspec-core (~> 3.9.0)
|
13
|
+
rspec-expectations (~> 3.9.0)
|
14
|
+
rspec-mocks (~> 3.9.0)
|
15
|
+
rspec-core (3.9.2)
|
16
|
+
rspec-support (~> 3.9.3)
|
17
|
+
rspec-expectations (3.9.2)
|
18
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
19
|
+
rspec-support (~> 3.9.0)
|
20
|
+
rspec-mocks (3.9.1)
|
21
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
22
|
+
rspec-support (~> 3.9.0)
|
23
|
+
rspec-support (3.9.3)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
ruby
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
bundler (~> 2.0, >= 2.0.1)
|
30
|
+
rake (~> 13.0)
|
31
|
+
rspec (~> 3.8)
|
32
|
+
rspec-expectations (~> 3.8)
|
33
|
+
tree-red_black!
|
34
|
+
|
35
|
+
BUNDLED WITH
|
36
|
+
2.1.4
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 TODO: Write your name
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,572 @@
|
|
1
|
+
[](https://travis-ci.com/slewsys/tree-red_black)
|
2
|
+
|
3
|
+
# Tree::RedBlack
|
4
|
+
|
5
|
+
- [Description](#description)
|
6
|
+
- [Installation](#installation)
|
7
|
+
- [Tree::RedBlack API](#treeredblack-api)
|
8
|
+
- [new(allow_duplicates = true) → red_black_tree](#newallow_duplicates--true--red_black_tree)
|
9
|
+
- [insert(value, ...) → red_black_tree](#insertvalue---red_black_tree)
|
10
|
+
- [delete(value, ...) → red_black_tree](#deletevalue---red_black_tree)
|
11
|
+
- [search(value, ifnone = nil) → red_black_node](#searchvalue-ifnone--nil--red_black_node)
|
12
|
+
- [bsearch { |node| block } → red_black_node](#bsearch--node-block---red_black_node)
|
13
|
+
- [pre_order → node_enumerator](#pre_order--node_enumerator)
|
14
|
+
- [in_order → node_enumerator](#in_order--node_enumerator)
|
15
|
+
- [dup → red_black_tree](#dup--red_black_tree)
|
16
|
+
- [Tree::RedBlackNode API](#treeredblacknode-api)
|
17
|
+
- [new(value = nil, color = :RED) → red_black_node](#newvalue--nil-color--red--red_black_node)
|
18
|
+
- [insert_red_black(value, allow_duplicates = true) → red_black_node](#insert_red_blackvalue-allow_duplicates--true--red_black_node)
|
19
|
+
- [delete_red_black(value) → red_black_node](#delete_red_blackvalue--red_black_node)
|
20
|
+
- [search(value, ifnone = nil) → red_black_node](#searchvalue-ifnone--nil--red_black_node-1)
|
21
|
+
- [bsearch(&block) → red_black_node](#bsearchblock--red_black_node)
|
22
|
+
- [min() → red_black_node](#min--red_black_node)
|
23
|
+
- [max() → red_black_node](#max--red_black_node)
|
24
|
+
- [pred() → red_black_node](#pred--red_black_node)
|
25
|
+
- [succ() → red_black_node](#succ--red_black_node)
|
26
|
+
- [pre_order(&block) → red_black_node](#pre_orderblock--red_black_node)
|
27
|
+
- [in_order(&block) → red_black_node](#in_orderblock--red_black_node)
|
28
|
+
- [dup() → red_black_node](#dup--red_black_node)
|
29
|
+
- [Contributing](#contributing)
|
30
|
+
- [License](#license)
|
31
|
+
|
32
|
+
## Description
|
33
|
+
|
34
|
+
The __Tree::RedBlack__ library is a pure-Ruby implementation of
|
35
|
+
a [Red-Black tree](https://en.wikipedia.org/wiki/Red–black_tree) --
|
36
|
+
i.e., a self-balancing binary tree
|
37
|
+
with [O(log n)](https://en.wikipedia.org/wiki/Big-O_notation) search,
|
38
|
+
insert and delete operations. It is appropriate for maintaining a
|
39
|
+
sorted collection where insertion and deletion are desired at
|
40
|
+
arbitrary positions.
|
41
|
+
|
42
|
+
This implementation differs slightly from the Wikipedia description
|
43
|
+
referenced above. In particular, leaf nodes are `nil`, which affects the
|
44
|
+
details of node deletion.
|
45
|
+
|
46
|
+
## Installation
|
47
|
+
With a recent version of the [Ruby](https://www.ruby-lang.org/en/)
|
48
|
+
interpreter installed (e.g., ruby 2.5), run the following commands
|
49
|
+
from a Unix shell:
|
50
|
+
|
51
|
+
```bash
|
52
|
+
git clone git@github.com:slewsys/tree-red_black.git
|
53
|
+
cd tree-red_black
|
54
|
+
sudo gem update --system
|
55
|
+
bundle
|
56
|
+
rake build
|
57
|
+
sudo gem install pkg/tree-red_black*.gem
|
58
|
+
```
|
59
|
+
|
60
|
+
The RSpec test suite can be run with:
|
61
|
+
|
62
|
+
```bash
|
63
|
+
bundle exec rspec spec
|
64
|
+
```
|
65
|
+
|
66
|
+
To build RDoc documentation, use:
|
67
|
+
|
68
|
+
```bash
|
69
|
+
rake rdoc
|
70
|
+
```
|
71
|
+
|
72
|
+
## Tree::RedBlack API
|
73
|
+
|
74
|
+
Once a Red-Black tree has been instantiated
|
75
|
+
(see
|
76
|
+
[new](#newallow_duplicates--true--red_black_tree)),
|
77
|
+
any [Comparable](https://docs.ruby-lang.org/en/2.7.0/Comparable.html)
|
78
|
+
value can be stored, provided that every value in the tree is
|
79
|
+
comparable with every other. Values are stored in nodes and referenced
|
80
|
+
by the `key` attribute of the node. Nodes are added to a Red-Black
|
81
|
+
tree by inserting values
|
82
|
+
(see
|
83
|
+
[insert](#insertvalue---red_black_tree)),
|
84
|
+
and nodes are removed by deleting values
|
85
|
+
(see
|
86
|
+
[delete](#deletevalue---red_black_tree)).
|
87
|
+
|
88
|
+
A Red-Black tree's nodes can be enumerated in ascending order by value
|
89
|
+
with the tree's [each](#in_order--node_enumerator) method. Additional
|
90
|
+
enumeration methods are described
|
91
|
+
in [Enumerable](https://ruby-doc.org/core-2.7.0/Enumerable.html).
|
92
|
+
|
93
|
+
### new(allow_duplicates = true) → red_black_tree
|
94
|
+
|
95
|
+
Returns a new, empty Red-Black tree. If option `allow_duplicates` is
|
96
|
+
`false`, then only unique values are inserted in a Red-Black tree.
|
97
|
+
|
98
|
+
The `root` attribute references the root node of the tree.
|
99
|
+
The `size` attribute indicates the number of nodes in the tree.
|
100
|
+
When `size` is `0`, `root` is always `nil`.
|
101
|
+
|
102
|
+
Example:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
require 'tree/red_black'
|
106
|
+
|
107
|
+
rbt = Tree::RedBlack.new
|
108
|
+
p rbt.root #=> nil
|
109
|
+
p rbt.size #=> 0
|
110
|
+
p rbt.allow_duplicates? #=> true
|
111
|
+
```
|
112
|
+
|
113
|
+
### insert(value, ...) → red_black_tree
|
114
|
+
|
115
|
+
Inserts a value or sequence of values in a Red-Black tree and
|
116
|
+
increments the `size` attribute by the number of values inserted.
|
117
|
+
|
118
|
+
Since a Red-Black tree maintains a sorted, [Enumerable](https://ruby-doc.org/core-2.7.0/Enumerable.html) collection,
|
119
|
+
every value inserted must be comparable with every other value.
|
120
|
+
Methods `each`, `map`, `select`, `find`, `sort`, etc., can be applied
|
121
|
+
directly to the tree.
|
122
|
+
|
123
|
+
The individual nodes yielded by enumeration respond to method `key` to
|
124
|
+
retrieve the value stored in that node. Method `each`, in particular,
|
125
|
+
is aliased to `in_order`, so that nodes are sorted in ascending order
|
126
|
+
by `key` value. Nodes can also be traversed by method `pre_order`,
|
127
|
+
e.g., to generate paths in the tree.
|
128
|
+
|
129
|
+
Example:
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
require 'tree/red_black'
|
133
|
+
|
134
|
+
rbt = Tree::RedBlack.new
|
135
|
+
rbt.insert(*1..10) # #<Tree::RedBlack:0x00...>
|
136
|
+
p rbt.size #=> 10
|
137
|
+
rbt.map(&:key) #=> [1, 2, ..., 10]
|
138
|
+
rbt.select { |node| node.key % 2 == 0 }.map(&:key)
|
139
|
+
#=> [2, 4, ..., 10]
|
140
|
+
```
|
141
|
+
|
142
|
+
### delete(value, ...) → red_black_tree
|
143
|
+
|
144
|
+
Deletes a value or sequence of values from a Red-Black tree.
|
145
|
+
|
146
|
+
Example:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
require 'tree/red_black'
|
150
|
+
|
151
|
+
rbt = Tree::RedBlack.new
|
152
|
+
rbt.insert(*1..10) # #<Tree::RedBlack:0x00...>
|
153
|
+
p rbt.size #=> 10
|
154
|
+
rbt.delete(*4..8) # #<Tree::RedBlack:0x00...>
|
155
|
+
p rbt.size #=> 5
|
156
|
+
rbt.map(&:key) #=> [1, 2, 3, 9, 10]
|
157
|
+
```
|
158
|
+
|
159
|
+
### search(value, ifnone = nil) → red_black_node
|
160
|
+
|
161
|
+
Returns a Red-Black tree node whose `key` matches `value` by binary
|
162
|
+
search. If no match is found, calls non-nil `ifnone`, otherwise
|
163
|
+
returns `nil`.
|
164
|
+
|
165
|
+
Example:
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
require 'tree/red_black'
|
169
|
+
|
170
|
+
shuffled_values = [*1..10].shuffle
|
171
|
+
rbt = shuffled_values.reduce(Tree::RedBlack.new) do |acc, v|
|
172
|
+
acc.insert(v)
|
173
|
+
end
|
174
|
+
rbt.search(7) #=> <Tree::RedBlackNode:0x00..., @key=7, ...>
|
175
|
+
```
|
176
|
+
|
177
|
+
### bsearch { |node| block } → red_black_node
|
178
|
+
|
179
|
+
Returns a Red-Black tree node satisfying a criterion defined in
|
180
|
+
`block` by binary search.
|
181
|
+
|
182
|
+
If `block` evaluates to `true` or `false`, returns the first node for
|
183
|
+
which the `block` evaluates to `true`. In this case, the criterion is
|
184
|
+
expected to return `false` for nodes preceding the matching node and
|
185
|
+
`true` for subsequent nodes.
|
186
|
+
|
187
|
+
Example:
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
require 'tree/red_black'
|
191
|
+
|
192
|
+
shuffled_values = [*1..10].shuffle
|
193
|
+
rbt = shuffled_values.reduce(Tree::RedBlack.new) do |acc, v|
|
194
|
+
acc.insert(v)
|
195
|
+
end
|
196
|
+
rbt.bsearch { |node| node.key >= 7 }
|
197
|
+
#=> <Tree::RedBlackNode:0x00..., @key=7, ...>
|
198
|
+
```
|
199
|
+
|
200
|
+
If `block` evaluates to `<0`, `0` or `>0`, returns first node for
|
201
|
+
which `block` evaluates to `0`. Otherwise returns `nil`. In this case,
|
202
|
+
the criterion is expected to return `<0` for nodes preceding the
|
203
|
+
matching node, `0` for some subsequent nodes and `>0` for nodes beyond
|
204
|
+
that.
|
205
|
+
|
206
|
+
Example:
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
require 'tree/red_black'
|
210
|
+
|
211
|
+
shuffled_values = [*1..10].shuffle
|
212
|
+
rbt = shuffled_values.reduce(Tree::RedBlack.new) do |acc, v|
|
213
|
+
acc.insert(v)
|
214
|
+
end
|
215
|
+
rbt.bsearch { |node| 7 <=> node.key }
|
216
|
+
#=> <Tree::RedBlackNode:0x00..., @key=7, ...>
|
217
|
+
```
|
218
|
+
|
219
|
+
If `block` is not given, returns an enumerator.
|
220
|
+
|
221
|
+
### pre_order → node_enumerator
|
222
|
+
|
223
|
+
Returns an enumerator for nodes in a Red-Black tree by pre-order
|
224
|
+
traversal.
|
225
|
+
|
226
|
+
Example:
|
227
|
+
|
228
|
+
```ruby
|
229
|
+
require 'tree/red_black'
|
230
|
+
|
231
|
+
rbt = Tree::RedBlack.new
|
232
|
+
shuffled_values = [*1..10].shuffle #=> [5, 9, 10, 8, 7, 6, 1, 2, 4, 3]
|
233
|
+
rbt.insert(*shuffled_values) #=> #<Tree::RedBlack:0x00...>
|
234
|
+
rbt.pre_order.map(&:key) #=> [7, 5, 2, 1, 4, 3, 6, 9, 8, 10]
|
235
|
+
```
|
236
|
+
|
237
|
+
### in_order → node_enumerator
|
238
|
+
|
239
|
+
Returns an enumerator for nodes in a Red-Black tree by in-order
|
240
|
+
traversal. The `each` method is aliased to `in_order`.
|
241
|
+
|
242
|
+
Example:
|
243
|
+
|
244
|
+
```ruby
|
245
|
+
require 'tree/red_black'
|
246
|
+
|
247
|
+
rbt = Tree::RedBlack.new
|
248
|
+
shuffled_values = [*1..10].shuffle
|
249
|
+
rbt.insert(*shuffled_values)
|
250
|
+
rbt.in_order.map(&:key) #=> [1, 2, ... 9, 10]
|
251
|
+
```
|
252
|
+
|
253
|
+
### dup → red_black_tree
|
254
|
+
|
255
|
+
Returns a deep copy of a Red-Black tree, provided that the `dup`
|
256
|
+
method for the `key` attribute of a tree node is also a deep copy.
|
257
|
+
|
258
|
+
Example:
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
require 'tree/red_black'
|
262
|
+
|
263
|
+
rbt = Tree::RedBlack.new
|
264
|
+
rbt.insert({a: 1, b: 2})
|
265
|
+
rbt_copy = rbt.dup
|
266
|
+
p rbt.root.key #=> {:a=>1, :b=>2}
|
267
|
+
p rbt.root.key.delete(:a) #=> 1
|
268
|
+
p rbt.root.key #=> {:b=>2}
|
269
|
+
p rbt_copy.root.key #=> {:a=>1, :b=>2}
|
270
|
+
```
|
271
|
+
|
272
|
+
### Tree::RedBlackNode API
|
273
|
+
|
274
|
+
A Red-Black tree is a collection of nodes arranged as a binary tree.
|
275
|
+
In addition to the binary node attributes `left` and `right`, which
|
276
|
+
reference the left and right sub-trees of a given node, and the
|
277
|
+
attribute `key` which stores a node's data, a Red-Black tree node
|
278
|
+
also has attributes `color` and `parent`.
|
279
|
+
|
280
|
+
The `color` attribute is used internally to balance the tree after a
|
281
|
+
node is inserted or deleted. The `parent` attribute references a
|
282
|
+
node's parent node, or `nil` in the case of the root node of a tree.
|
283
|
+
|
284
|
+
Not all implementations of Red-Black trees have nodes with `parent`
|
285
|
+
attributes, but it's generally recognized as the most efficient way
|
286
|
+
of balancing and re-coloring a Red-Black tree.
|
287
|
+
|
288
|
+
Since the data in a binary tree can be thought of as a sorted
|
289
|
+
collection, it's convenient to be able to refer to a node's
|
290
|
+
predecessor and successor (i.e., the node whose `key` is the
|
291
|
+
predecessor or successor in the sorted ascending order. In general,
|
292
|
+
this differs from parent or child node). This is provided as the node
|
293
|
+
methods `pred` and `succ`. And for a given sub-tree, its convenient to
|
294
|
+
be able to refer to its min and max nodes (i.e., the node whose `key`
|
295
|
+
is a minimum or maximum in the sub-tree). This is provided as the node
|
296
|
+
methods `min` and `max`.
|
297
|
+
|
298
|
+
While a Red-Black tree can be constructed from nodes alone, the
|
299
|
+
[Tree::RedBlack API](#treeredblack-api)
|
300
|
+
provides a cleaner way of working with Red-Black trees. Start
|
301
|
+
there if only using the Red-Black tree as a container.
|
302
|
+
|
303
|
+
### new(value = nil, color = :RED) → red_black_node
|
304
|
+
|
305
|
+
Returns a new node with `key` parameter set to option `value`. The
|
306
|
+
`color` option, if given, must be be either `:RED` or `:BLACK`.
|
307
|
+
|
308
|
+
Example:
|
309
|
+
|
310
|
+
```ruby
|
311
|
+
require 'tree/red_black'
|
312
|
+
|
313
|
+
root = Tree::RedBlackNode.new(10)
|
314
|
+
p root.key #=> 10
|
315
|
+
p root.color #=> :RED
|
316
|
+
p root.parent #=> nil
|
317
|
+
p root.left #=> nil
|
318
|
+
p root.right #=> nil
|
319
|
+
```
|
320
|
+
|
321
|
+
### insert_red_black(value, allow_duplicates = true) → red_black_node
|
322
|
+
|
323
|
+
Inserts the given `value` in a tree whose root node is `self`. If the
|
324
|
+
`key` attribute of the root node is `nil`, then `value` is assigned to
|
325
|
+
`key`. Otherwise, `value` is used to instantiate Tree::RedBlackNode,
|
326
|
+
and the node is inserted in the tree; the tree is then re-balanced as
|
327
|
+
needed, and the root of the balanced tree returned.
|
328
|
+
|
329
|
+
Since a Red-Black tree maintains an ordered, Enumerable collection,
|
330
|
+
every value inserted must be Comparable with every other value.
|
331
|
+
Methods `each`, `map`, `select`, `find`, `sort`, etc., can be applied
|
332
|
+
to a Red-Black tree's root node to iterate over all nodes in the tree.
|
333
|
+
|
334
|
+
Each node yielded by enumeration has a `key` attribute to
|
335
|
+
retrieve the value stored in that node. Method `each`, in particular,
|
336
|
+
is aliased to `in_order`, so that nodes are sorted in ascending order
|
337
|
+
by `key` value. Nodes can also be traversed by method `pre_order`,
|
338
|
+
e.g., to generate paths in the tree.
|
339
|
+
|
340
|
+
Example:
|
341
|
+
|
342
|
+
```ruby
|
343
|
+
require 'tree/red_black'
|
344
|
+
|
345
|
+
root = Tree::RedBlackNode.new
|
346
|
+
p root.key #=> nil
|
347
|
+
root = root.insert_red_black(0)
|
348
|
+
p root.key #=> 0
|
349
|
+
root = root.insert_red_black(1)
|
350
|
+
p root.key #=> 0
|
351
|
+
p root.left #=> nil
|
352
|
+
p root.right.key #=> 1
|
353
|
+
root = root.insert_red_black(2)
|
354
|
+
p root.key #=> 1
|
355
|
+
p root.left.key #=> 0
|
356
|
+
p root.right.key #=> 2
|
357
|
+
```
|
358
|
+
|
359
|
+
### delete_red_black(value) → red_black_node
|
360
|
+
|
361
|
+
Deletes the given `value` from a tree whose root node is `self`.
|
362
|
+
If the tree has only one remaining node and its `key` attribute
|
363
|
+
matches `value`, then the remaining node's `key` attribute is set to
|
364
|
+
`nil` but the node itself is not removed. Otherwise, the first node
|
365
|
+
found whose `key` matches `value` is removed from the tree, and the
|
366
|
+
tree is re-balanced. The root of the balanced tree is returned.
|
367
|
+
|
368
|
+
Example:
|
369
|
+
|
370
|
+
```ruby
|
371
|
+
require 'tree/red_black'
|
372
|
+
|
373
|
+
root = [*1..10].reduce(Tree::RedBlackNode.new) do |acc, v|
|
374
|
+
acc.insert_red_black(v)
|
375
|
+
end
|
376
|
+
root = [*4..8].reduce(root) do |acc, v|
|
377
|
+
acc.delete_red_black(v)
|
378
|
+
end
|
379
|
+
root.map(&:key) #=> [1, 2, 3, 9, 10]
|
380
|
+
```
|
381
|
+
|
382
|
+
### search(value, ifnone = nil) → red_black_node
|
383
|
+
|
384
|
+
Returns a node whose `key` matches `value` by binary search. If no
|
385
|
+
match is found, calls non-nil `ifnone`, otherwise returns `nil`.
|
386
|
+
|
387
|
+
Example:
|
388
|
+
|
389
|
+
```ruby
|
390
|
+
require 'tree/red_black'
|
391
|
+
|
392
|
+
shuffled_values = [*1..10].shuffle
|
393
|
+
root = shuffled_values.reduce(Tree::RedBlackNode.new) do |acc, v|
|
394
|
+
acc.insert_red_black(v)
|
395
|
+
end
|
396
|
+
root.search(7) #=> <Tree::RedBlackNode:0x00..., @key=7, ...>
|
397
|
+
```
|
398
|
+
|
399
|
+
### bsearch(&block) → red_black_node
|
400
|
+
|
401
|
+
Returns a node satisfying a criterion defined in `block` by binary
|
402
|
+
search.
|
403
|
+
|
404
|
+
If `block` evaluates to `true` or `false`, returns the first node for
|
405
|
+
which the `block` evaluates to `true`. In this case, the criterion is
|
406
|
+
expected to return `false` for nodes preceding the matching node and
|
407
|
+
`true` for subsequent nodes.
|
408
|
+
|
409
|
+
Example:
|
410
|
+
|
411
|
+
```ruby
|
412
|
+
require 'tree/red_black'
|
413
|
+
|
414
|
+
shuffled_values = [*1..10].shuffle
|
415
|
+
rbt = shuffled_values.reduce(Tree::RedBlack.new) do |acc, v|
|
416
|
+
acc.insert(v)
|
417
|
+
end
|
418
|
+
rbt.bsearch { |node| node.key >= 7 }
|
419
|
+
#=> <Tree::RedBlackNode:0x00..., @key=7, ...>
|
420
|
+
```
|
421
|
+
|
422
|
+
If `block` evaluates to `<0`, `0` or `>0`, returns first node for
|
423
|
+
which `block` evaluates to `0`. Otherwise returns `nil`. In this case,
|
424
|
+
the criterion is expected to return `<0` for nodes preceding the
|
425
|
+
matching node, `0` for some subsequent nodes and `>0` for nodes beyond
|
426
|
+
that.
|
427
|
+
|
428
|
+
Example:
|
429
|
+
|
430
|
+
```ruby
|
431
|
+
require 'tree/red_black'
|
432
|
+
|
433
|
+
shuffled_values = [*1..10].shuffle
|
434
|
+
rbt = shuffled_values.reduce(Tree::RedBlack.new) do |acc, v|
|
435
|
+
acc.insert(v)
|
436
|
+
end
|
437
|
+
rbt.bsearch { |node| 7 <=> node.key }
|
438
|
+
#=> <Tree::RedBlackNode:0x00..., @key=7, ...>
|
439
|
+
```
|
440
|
+
|
441
|
+
If `block` is not given, returns an enumerator.
|
442
|
+
|
443
|
+
### min() → red_black_node
|
444
|
+
|
445
|
+
Returns the node whose `key` is a minimum in the sub-tree with root `self`.
|
446
|
+
|
447
|
+
Example:
|
448
|
+
|
449
|
+
```ruby
|
450
|
+
require 'tree/red_black'
|
451
|
+
|
452
|
+
root = [*0..10].reduce(Tree::RedBlackNode.new) do |acc, v|
|
453
|
+
acc.insert_red_black(v)
|
454
|
+
end
|
455
|
+
root #=> <Tree::RedBlackNode:0x00..., @key=4, ...>
|
456
|
+
root.min #=> <Tree::RedBlackNode:0x00..., @key=0, ...>
|
457
|
+
root.right #=> <Tree::RedBlackNode:0x00..., @key=6, ...>
|
458
|
+
root.right.min #=> <Tree::RedBlackNode:0x00..., @key=5, ...>
|
459
|
+
```
|
460
|
+
### max() → red_black_node
|
461
|
+
|
462
|
+
Returns the node whose `key` is a maximum in the sub-tree with
|
463
|
+
root `self`.
|
464
|
+
|
465
|
+
Example:
|
466
|
+
|
467
|
+
```ruby
|
468
|
+
require 'tree/red_black'
|
469
|
+
|
470
|
+
root = [*0..10].reduce(Tree::RedBlackNode.new) do |acc, v|
|
471
|
+
acc.insert_red_black(v)
|
472
|
+
end
|
473
|
+
root #=> <Tree::RedBlackNode:0x00..., @key=4, ...>
|
474
|
+
root.max #=> <Tree::RedBlackNode:0x00..., @key=10, ...>
|
475
|
+
root.left #=> <Tree::RedBlackNode:0x00..., @key=2, ...>
|
476
|
+
root.left.max #=> <Tree::RedBlackNode:0x00..., @key=3, ...>
|
477
|
+
```
|
478
|
+
|
479
|
+
### pred() → red_black_node
|
480
|
+
|
481
|
+
Returns the node preceding `self`, or `nil` if no predecessor exists.
|
482
|
+
If duplicate keys are allowed, it's possible that `pred.key == key`.
|
483
|
+
|
484
|
+
Example:
|
485
|
+
|
486
|
+
```ruby
|
487
|
+
require 'tree/red_black'
|
488
|
+
|
489
|
+
root = [*1..10].reduce(Tree::RedBlackNode.new) do |acc, v|
|
490
|
+
acc.insert_red_black(v)
|
491
|
+
end
|
492
|
+
root.right.right.key #=> 8
|
493
|
+
root.right.right.pred.key #=> 7
|
494
|
+
```
|
495
|
+
|
496
|
+
### succ() → red_black_node
|
497
|
+
|
498
|
+
Returns the node succeeding `self`, or `nil` if no successor exists.
|
499
|
+
If duplicate keys are allowed, it's possible that `succ.key == key`.
|
500
|
+
|
501
|
+
Example:
|
502
|
+
|
503
|
+
```ruby
|
504
|
+
require 'tree/red_black'
|
505
|
+
|
506
|
+
root = [*1..10].reduce(Tree::RedBlackNode.new) do |acc, v|
|
507
|
+
acc.insert_red_black(v)
|
508
|
+
end
|
509
|
+
root.right.right.key #=> 8
|
510
|
+
root.right.right.succ.key #=> 9
|
511
|
+
```
|
512
|
+
|
513
|
+
### pre_order(&block) → red_black_node
|
514
|
+
|
515
|
+
Returns an enumerator for nodes in the tree with root `self` by
|
516
|
+
pre-order traversal.
|
517
|
+
|
518
|
+
Example:
|
519
|
+
|
520
|
+
```ruby
|
521
|
+
require 'tree/red_black'
|
522
|
+
|
523
|
+
root = [*1..10].reduce(Tree::RedBlackNode.new) do |acc, v|
|
524
|
+
acc.insert_red_black(v)
|
525
|
+
end
|
526
|
+
root.pre_order.map(&:key) #=> [4, 2, 1, 3, 6, 5, 8, 7, 9, 10]
|
527
|
+
```
|
528
|
+
|
529
|
+
### in_order(&block) → red_black_node
|
530
|
+
|
531
|
+
Returns an enumerator for nodes in the tree with root `self` by
|
532
|
+
in-order traversal.
|
533
|
+
|
534
|
+
Example:
|
535
|
+
|
536
|
+
```ruby
|
537
|
+
require 'tree/red_black'
|
538
|
+
|
539
|
+
root = [*1..10].reduce(Tree::RedBlackNode.new) do |acc, v|
|
540
|
+
acc.insert_red_black(v)
|
541
|
+
end
|
542
|
+
root.in_order.map(&:key) #=> [1, 2, ..., 10]
|
543
|
+
```
|
544
|
+
|
545
|
+
### dup() → red_black_node
|
546
|
+
|
547
|
+
Returns a deep copy of the tree with root `self`, provided that
|
548
|
+
the `dup` method for the `key` attribute of a node is also a
|
549
|
+
deep copy.
|
550
|
+
|
551
|
+
Example:
|
552
|
+
|
553
|
+
```ruby
|
554
|
+
require 'tree/red_black'
|
555
|
+
|
556
|
+
root = Tree::RedBlackNode.new({a: 1, b: 2})
|
557
|
+
root_copy = root.dup
|
558
|
+
p root.key #=> {:a=>1, :b=>2}
|
559
|
+
p root.key.delete(:a) #=> 1
|
560
|
+
p root.key #=> {:b=>2}
|
561
|
+
p root_copy.key #=> {:a=>1, :b=>2}
|
562
|
+
```
|
563
|
+
|
564
|
+
## Contributing
|
565
|
+
|
566
|
+
Bug reports and pull requests can be sent to
|
567
|
+
[GitHub tree-red_black](https://github.com/slewsys/tree-red_black).
|
568
|
+
|
569
|
+
## License
|
570
|
+
|
571
|
+
This Rubygem is free software. It can be used and redistributed under
|
572
|
+
the terms of the [MIT License](http://opensource.org/licenses/MIT).
|