red-black-tree 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4f43951dbc99839bcb925622284650c9f5ec3dbe3fa709706fac32345bbe1607
4
+ data.tar.gz: 8d1d5cdc4420b9e29012ed4a16054f0bede9b9239327605151f97efc123d0636
5
+ SHA512:
6
+ metadata.gz: b3f59b93fc6d1f5e10081f5f72d9c8346c4e117badc7f3ac5d694bac07308c511fc3ed71cb4b250c5d790fd6d77f13b219fd1d9accbd7120783147862ce52045
7
+ data.tar.gz: 42d421b0ab688c03ea073ef34d460ed42cb3de4f14b5aa13ec4f243bf71fbc65533da0a2a7ee390ea33fc5828549bc62f514f3a592c0f42d179f3d4a693c6ab2
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2024-08-04
4
+
5
+ - Initial release
@@ -0,0 +1,132 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, caste, color, religion, or sexual
10
+ identity and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ * Demonstrating empathy and kindness toward other people
21
+ * Being respectful of differing opinions, viewpoints, and experiences
22
+ * Giving and gracefully accepting constructive feedback
23
+ * Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ * Focusing on what is best not just for us as individuals, but for the overall
26
+ community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ * The use of sexualized language or imagery, and sexual attention or advances of
31
+ any kind
32
+ * Trolling, insulting or derogatory comments, and personal or political attacks
33
+ * Public or private harassment
34
+ * Publishing others' private information, such as a physical or email address,
35
+ without their explicit permission
36
+ * Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official email address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement at
63
+ [INSERT CONTACT METHOD].
64
+ All complaints will be reviewed and investigated promptly and fairly.
65
+
66
+ All community leaders are obligated to respect the privacy and security of the
67
+ reporter of any incident.
68
+
69
+ ## Enforcement Guidelines
70
+
71
+ Community leaders will follow these Community Impact Guidelines in determining
72
+ the consequences for any action they deem in violation of this Code of Conduct:
73
+
74
+ ### 1. Correction
75
+
76
+ **Community Impact**: Use of inappropriate language or other behavior deemed
77
+ unprofessional or unwelcome in the community.
78
+
79
+ **Consequence**: A private, written warning from community leaders, providing
80
+ clarity around the nature of the violation and an explanation of why the
81
+ behavior was inappropriate. A public apology may be requested.
82
+
83
+ ### 2. Warning
84
+
85
+ **Community Impact**: A violation through a single incident or series of
86
+ actions.
87
+
88
+ **Consequence**: A warning with consequences for continued behavior. No
89
+ interaction with the people involved, including unsolicited interaction with
90
+ those enforcing the Code of Conduct, for a specified period of time. This
91
+ includes avoiding interactions in community spaces as well as external channels
92
+ like social media. Violating these terms may lead to a temporary or permanent
93
+ ban.
94
+
95
+ ### 3. Temporary Ban
96
+
97
+ **Community Impact**: A serious violation of community standards, including
98
+ sustained inappropriate behavior.
99
+
100
+ **Consequence**: A temporary ban from any sort of interaction or public
101
+ communication with the community for a specified period of time. No public or
102
+ private interaction with the people involved, including unsolicited interaction
103
+ with those enforcing the Code of Conduct, is allowed during this period.
104
+ Violating these terms may lead to a permanent ban.
105
+
106
+ ### 4. Permanent Ban
107
+
108
+ **Community Impact**: Demonstrating a pattern of violation of community
109
+ standards, including sustained inappropriate behavior, harassment of an
110
+ individual, or aggression toward or disparagement of classes of individuals.
111
+
112
+ **Consequence**: A permanent ban from any sort of public interaction within the
113
+ community.
114
+
115
+ ## Attribution
116
+
117
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118
+ version 2.1, available at
119
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
120
+
121
+ Community Impact Guidelines were inspired by
122
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
123
+
124
+ For answers to common questions about this code of conduct, see the FAQ at
125
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
126
+ [https://www.contributor-covenant.org/translations][translations].
127
+
128
+ [homepage]: https://www.contributor-covenant.org
129
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
130
+ [Mozilla CoC]: https://github.com/mozilla/diversity
131
+ [FAQ]: https://www.contributor-covenant.org/faq
132
+ [translations]: https://www.contributor-covenant.org/translations
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Joshua Young
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,59 @@
1
+ # RedBlackTree
2
+
3
+ [Red-black tree](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree) data structure for Ruby.
4
+
5
+ ## Installation
6
+
7
+ Install the gem and add to the application's Gemfile by executing:
8
+
9
+ $ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
10
+
11
+ If bundler is not being used to manage dependencies, install the gem by executing:
12
+
13
+ $ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
14
+
15
+ ## Usage
16
+
17
+ ```ruby
18
+ Work = Struct.new :min_latency, keyword_init: true
19
+
20
+ class WorkNode < RedBlackTree::Node
21
+ def <=> other
22
+ if other.instance_of? RedBlackTree::LeafNode
23
+ 1
24
+ else
25
+ self.data.min_latency <=> other.data.min_latency
26
+ end
27
+ end
28
+ end
29
+
30
+ tree = RedBlackTree.new
31
+
32
+ tree << WorkNode.new(Work.new min_latency: 1.2)
33
+ tree << WorkNode.new(Work.new min_latency: 0.8)
34
+ tree << WorkNode.new(Work.new min_latency: 0.8)
35
+ tree << WorkNode.new(Work.new min_latency: 0.4)
36
+
37
+ until tree.empty?
38
+ work = tree.shift # 0.4, 0.8, 0.8, 1.2
39
+ # process work
40
+ end
41
+ ```
42
+
43
+ ## Development
44
+
45
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake test` to run the
46
+ tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
47
+
48
+ ## Contributing
49
+
50
+ Bug reports and pull requests are welcome on GitHub at https://github.com/joshuay03/red-black-tree.
51
+
52
+ ## License
53
+
54
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
55
+
56
+ ## Code of Conduct
57
+
58
+ Everyone interacting in the RedBlackTree project's codebases, issue trackers, chat rooms and mailing lists is expected
59
+ to follow the [code of conduct](https://github.com/joshuay03/red-black-tree/blob/main/CODE_OF_CONDUCT.md).
@@ -0,0 +1,271 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "red_black_tree/utils"
4
+ require_relative "red_black_tree/node"
5
+ require_relative "red_black_tree/node/leaf_node"
6
+
7
+ class RedBlackTree
8
+ include Utils
9
+
10
+ # @return [Integer] the number of valid/non-leaf nodes
11
+ attr_reader :size
12
+
13
+ # @private
14
+ # @return [RedBlackTree::Node, nil] the root node
15
+ attr_reader :root
16
+
17
+ # @private
18
+ # @return [RedBlackTree::Node, nil] the left most node
19
+ attr_reader :left_most_node
20
+
21
+ def initialize
22
+ @size = 0
23
+ @left_most_node = nil
24
+ end
25
+
26
+ # Returns true if there are no valid/non-leaf nodes, and false if there are.
27
+ #
28
+ # @return [true, false]
29
+ def empty?
30
+ @size == 0
31
+ end
32
+
33
+ # Returns true if there are any valid/non-leaf nodes, and false if there are none.
34
+ #
35
+ # @return [true, false]
36
+ def any?
37
+ !empty?
38
+ end
39
+
40
+ # Removes the left most node (the node with the lowest data value) from the tree.
41
+ #
42
+ # @return [RedBlackTree::Node, nil] the removed node
43
+ def shift
44
+ node = @left_most_node
45
+ delete! node if node
46
+ node
47
+ end
48
+
49
+ # Traverses the tree, comparing existing nodes to the node to be added,
50
+ # and inserts the node with the appropriate parent and direction.
51
+ #
52
+ # @param node [RedBlackTree::Node] the node to be added
53
+ # @return [RedBlackTree] self
54
+ def << node
55
+ raise ArgumentError, "cannot add leaf node" if node.instance_of? LeafNode
56
+
57
+ parent = @root
58
+ direction = nil
59
+
60
+ while parent
61
+ direction = node >= parent ? Node::RIGHT : Node::LEFT
62
+ break if (child = parent[direction]).leaf?
63
+
64
+ parent = child
65
+ end
66
+
67
+ insert! node, parent, direction
68
+ end
69
+ alias_method :add!, :<<
70
+
71
+ # Inserts the given node using the given direction relative to the given parent.
72
+ #
73
+ # @private ideally this is only used internally e.g. in #<< which has context on the ideal location for the node
74
+ # @param node [RedBlackTree::Node] the node to be inserted
75
+ # @param target_parent [RedBlackTree::Node, nil] the parent under which the node should be inserted
76
+ # @param direction ["left", "right", nil] the direction of the node relative to the parent
77
+ # @return [RedBlackTree] self
78
+ def insert! node, target_parent = nil, direction = nil
79
+ raise ArgumentError, "cannot insert leaf node" if node.instance_of? LeafNode
80
+
81
+ if target_parent.nil?
82
+ raise ArgumentError, "Target parent must be provided for tree with root" if @root
83
+ else
84
+ raise ArgumentError, "Target parent direction must be provided" if direction.nil?
85
+ raise ArgumentError, "Target parent already has #{direction} child" if (child = target_parent[direction]) && child.valid?
86
+ end
87
+
88
+ opp_direction = opposite_direction direction if direction
89
+
90
+ node.parent = nil
91
+ node.left = LeafNode.new
92
+ node.left.parent = node
93
+ node.right = LeafNode.new
94
+ node.right.parent = node
95
+
96
+ if target_parent.nil?
97
+ @root = node
98
+ @root.black!
99
+ else
100
+ target_parent[direction] = node
101
+ node.parent = target_parent
102
+ node.red!
103
+
104
+ while node.parent && node.parent.red? do
105
+ if node.parent.sibling && node.parent.sibling.red?
106
+ node.parent.black!
107
+ node.parent.sibling.black!
108
+ node.parent.parent.red!
109
+ node = node.parent.parent
110
+ else
111
+ if node.position == direction
112
+ node = node.parent
113
+ rotate_sub_tree! node, opp_direction
114
+ end
115
+
116
+ node.parent.black!
117
+
118
+ if node.parent.parent
119
+ node.parent.parent.red!
120
+ rotate_sub_tree! node.parent.parent, direction
121
+ end
122
+ end
123
+
124
+ @root.black!
125
+ end
126
+ end
127
+
128
+ node.validate! @root == node
129
+
130
+ increment_size!
131
+ update_left_most_node!
132
+
133
+ self
134
+ end
135
+
136
+ # Removes the given node from the tree.
137
+ #
138
+ # @param node [RedBlackTree::Node] the node to be removed
139
+ # @return [RedBlackTree] self
140
+ def delete! node
141
+ raise ArgumentError, "cannot delete leaf node" if node.instance_of? LeafNode
142
+
143
+ if node.children_are_valid?
144
+ successor = node.left
145
+ successor = successor.left until successor.left.leaf?
146
+ node.swap_data_with! successor
147
+
148
+ return delete! successor
149
+ elsif node.single_child_is_valid?
150
+ is_root = is_root? node
151
+
152
+ valid_child = node.children.find(&:valid?)
153
+ node.swap_data_with! valid_child
154
+ node.black!
155
+
156
+ @root = node if is_root
157
+
158
+ return delete! valid_child
159
+ elsif node.children_are_leaves?
160
+ if is_root? node
161
+ @root = nil
162
+ elsif node.red?
163
+ leaf = LeafNode.new
164
+ node.swap_position_with! leaf
165
+ else
166
+ direction = node.position
167
+ opp_direction = opposite_direction direction
168
+
169
+ loop do
170
+ if node.sibling.valid? && node.sibling.red?
171
+ node.parent.red!
172
+ node.sibling.black!
173
+ rotate_sub_tree! node.parent, direction
174
+
175
+ next
176
+ end
177
+
178
+ if node.distant_nephew && node.distant_nephew.valid? && node.distant_nephew.red?
179
+ case node.parent.colour
180
+ when Node::RED then node.sibling.red!
181
+ when Node::BLACK then node.sibling.black!
182
+ end
183
+ node.parent.black!
184
+ node.distant_nephew.black!
185
+ rotate_sub_tree! node.parent, direction
186
+
187
+ break
188
+ end
189
+
190
+ if node.close_nephew && node.close_nephew.valid? && node.close_nephew.red?
191
+ node.sibling.red!
192
+ node.close_nephew.black!
193
+ rotate_sub_tree! node.sibling, opp_direction
194
+
195
+ next
196
+ end
197
+
198
+ if node.parent.red?
199
+ node.sibling.red!
200
+ node.parent.black!
201
+
202
+ break
203
+ end
204
+
205
+ break
206
+ end
207
+
208
+ leaf = LeafNode.new
209
+ node.swap_position_with! leaf
210
+ end
211
+ end
212
+
213
+ node.validate_free!
214
+
215
+ decrement_size!
216
+ update_left_most_node!
217
+
218
+ self
219
+ end
220
+
221
+ private
222
+
223
+ def is_root? node
224
+ node.object_id == @root.object_id
225
+ end
226
+
227
+ # Rotates a (sub-)tree starting from the given node in the given direction.
228
+ #
229
+ # @param node [RedBlackTree::Node] the root node of the sub-tree
230
+ # @param direction ["left", "right"] the direction of rotation
231
+ # @return [RedBlackTree::Node] the new root node of the sub-tree
232
+ def rotate_sub_tree! node, direction
233
+ opp_direction = opposite_direction direction
234
+ opp_direction_child = node[opp_direction]
235
+ return node unless opp_direction_child.valid?
236
+
237
+ node[opp_direction] = opp_direction_child[direction]
238
+ opp_direction_child[direction].parent = node
239
+
240
+ opp_direction_child.parent = node.parent
241
+ if node.parent
242
+ node.parent[node.position] = opp_direction_child
243
+ else
244
+ @root = opp_direction_child
245
+ end
246
+
247
+ opp_direction_child[direction] = node
248
+ node.parent = opp_direction_child
249
+
250
+ opp_direction_child
251
+ end
252
+
253
+ def increment_size!
254
+ @size += 1
255
+ end
256
+
257
+ def decrement_size!
258
+ @size -= 1
259
+ end
260
+
261
+ def update_left_most_node!
262
+ unless @root
263
+ @left_most_node = nil
264
+ return
265
+ end
266
+
267
+ current = @root
268
+ current = current.left until current.left.leaf?
269
+ @left_most_node = current
270
+ end
271
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../node"
4
+
5
+ class RedBlackTree
6
+ class LeafNode < Node # @private
7
+ def initialize
8
+ super nil
9
+
10
+ @colour = BLACK
11
+ end
12
+
13
+ def <=> other
14
+ (other.instance_of? LeafNode) ? 0 : -1
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RedBlackTree
4
+ class Node
5
+ module LeftRightElementReferencers # @private
6
+ def [] direction
7
+ case direction
8
+ when Node::LEFT then @left
9
+ when Node::RIGHT then @right
10
+ else raise ArgumentError, "Direction must be one of #{DIRECTIONS}"
11
+ end
12
+ end
13
+
14
+ def []= direction, node
15
+ case direction
16
+ when Node::LEFT then @left = node
17
+ when Node::RIGHT then @right = node
18
+ else raise ArgumentError, "Direction must be one of #{DIRECTIONS}"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "utils"
4
+ require_relative "node/left_right_element_referencers"
5
+
6
+ class RedBlackTree
7
+ class Node
8
+ include Comparable
9
+
10
+ # @return [any] the data/value representing the node
11
+ attr_reader :data
12
+
13
+ # @param data [any] a non-nil data/value representing the node
14
+ # @return [Node] a new instance of Node
15
+ def initialize data
16
+ raise ArgumentError, "data cannot be nil" if data.nil? && !(instance_of? RedBlackTree::LeafNode)
17
+
18
+ @data = data
19
+ @colour = nil
20
+ @parent = @left = @right = nil
21
+
22
+ validate_free!
23
+ end
24
+
25
+ # Needs to be implemented in a subclass of {Node}.
26
+ # Will be used to calculate the ideal position of this node when adding it
27
+ # to a tree.
28
+ def <=> other
29
+ raise NotImplementedError, "Comparable operator <=> must be implemented in subclass"
30
+ end
31
+
32
+ module Implementation # @private
33
+ class StructuralError < StandardError; end
34
+
35
+ include Utils
36
+
37
+ RED = "red"
38
+ BLACK = "black"
39
+ COLOURS = [RED, BLACK].freeze
40
+
41
+ LEFT = "left"
42
+ RIGHT = "right"
43
+ DIRECTIONS = [LEFT, RIGHT].freeze
44
+
45
+ attr_reader :colour
46
+ attr_writer :data
47
+ attr_accessor :tree, :parent
48
+ attr_accessor :left, :right
49
+ include LeftRightElementReferencers
50
+
51
+ def red? = @colour == RED
52
+ def red! = @colour = RED
53
+
54
+ def black? = @colour == BLACK
55
+ def black! = @colour = BLACK
56
+
57
+ def leaf? = black? && (instance_of? RedBlackTree::LeafNode)
58
+ def valid? = (red? || black?) && !(instance_of? RedBlackTree::LeafNode)
59
+
60
+ def children_are_leaves? = children.all?(&:leaf?)
61
+ def children_are_valid? = children.all?(&:valid?)
62
+ def single_child_is_leaf? = children.any?(&:leaf?) && !children_are_leaves?
63
+ alias_method :single_child_is_valid?, :single_child_is_leaf?
64
+
65
+ def position
66
+ return unless @parent
67
+
68
+ case self
69
+ when @parent.left then LEFT
70
+ when @parent.right then RIGHT
71
+ else raise StructuralError, "Disowned by parent"
72
+ end
73
+ end
74
+
75
+ def opposite_position
76
+ return unless @parent
77
+
78
+ opposite_direction position
79
+ end
80
+
81
+ def children
82
+ [@left, @right]
83
+ end
84
+
85
+ def sibling
86
+ return unless @parent
87
+
88
+ @parent[opposite_position]
89
+ end
90
+
91
+ def close_nephew
92
+ return unless sibling
93
+
94
+ sibling[position]
95
+ end
96
+
97
+ def distant_nephew
98
+ return unless sibling
99
+
100
+ sibling[opposite_position]
101
+ end
102
+
103
+ def validate! is_root = false
104
+ return if (@parent || is_root) && @left && @right
105
+
106
+ raise StructuralError, "Node is invalid"
107
+ end
108
+
109
+ def validate_free!
110
+ anchors = []
111
+ anchors << "parent" if @parent
112
+ anchors << "left child" if @left && @left.valid?
113
+ anchors << "right child" if @right && @right.valid?
114
+ return if anchors.empty?
115
+
116
+ raise StructuralError, "Node is still chained to #{anchors.join(", ")}"
117
+ end
118
+
119
+ def swap_data_with! other_node
120
+ temp_data = @data
121
+ @data = other_node.data
122
+ other_node.data = temp_data
123
+ end
124
+
125
+ def swap_colour_with! other_node
126
+ temp_colour = @colour
127
+
128
+ case other_node.colour
129
+ when RED then red!
130
+ when BLACK then black!
131
+ end
132
+
133
+ case temp_colour
134
+ when RED then other_node.red!
135
+ when BLACK then other_node.black!
136
+ end
137
+ end
138
+
139
+ def swap_position_with! other_node
140
+ self_position = position
141
+ other_position = other_node.position
142
+
143
+ if other_node.parent == self
144
+ self[other_position] = other_node[other_position]
145
+ other_node[other_position] = self
146
+
147
+ other_node.parent = @parent
148
+ @parent = other_node
149
+ elsif other_node == @parent
150
+ other_node[self_position] = self[self_position]
151
+ self[self_position] = other_node
152
+
153
+ temp_parent = other_node.parent
154
+ other_node.parent = self
155
+ @parent = temp_parent
156
+ else
157
+ other_node.parent[other_position] = self if other_node.parent
158
+ @parent[self_position] = other_node if @parent
159
+
160
+ temp_parent = other_node.parent
161
+ other_node.parent = @parent
162
+ @parent = temp_parent
163
+ end
164
+ end
165
+ end
166
+
167
+ self.include Implementation
168
+ end
169
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RedBlackTree
4
+ module Utils # @private
5
+ private
6
+
7
+ def opposite_direction direction
8
+ case direction
9
+ when "up" then "down"
10
+ when "right" then "left"
11
+ when "down" then "up"
12
+ when "left" then "right"
13
+ else raise ArgumentError, "Invalid direction"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RedBlackTree
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/red_black_tree/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "red-black-tree"
7
+ spec.version = RedBlackTree::VERSION
8
+ spec.authors = ["Joshua Young"]
9
+ spec.email = ["djry1999@gmail.com"]
10
+
11
+ spec.summary = "Red-Black Tree Data Structure for Ruby"
12
+ spec.homepage = "https://github.com/joshuay03/red-black-tree"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = ">= 3.0.0"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["documentation_uri"] = "https://joshuay03.github.io/red-black-tree/"
18
+ spec.metadata["source_code_uri"] = spec.homepage
19
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
20
+
21
+ spec.files = Dir["{lib}/**/*", "**/*.{gemspec,md,txt}"]
22
+ spec.require_paths = ["lib"]
23
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: red-black-tree
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Joshua Young
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-08-03 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - djry1999@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - CHANGELOG.md
21
+ - CODE_OF_CONDUCT.md
22
+ - LICENSE.txt
23
+ - README.md
24
+ - lib/red-black-tree.rb
25
+ - lib/red_black_tree/node.rb
26
+ - lib/red_black_tree/node/leaf_node.rb
27
+ - lib/red_black_tree/node/left_right_element_referencers.rb
28
+ - lib/red_black_tree/utils.rb
29
+ - lib/red_black_tree/version.rb
30
+ - red-black-tree.gemspec
31
+ homepage: https://github.com/joshuay03/red-black-tree
32
+ licenses:
33
+ - MIT
34
+ metadata:
35
+ homepage_uri: https://github.com/joshuay03/red-black-tree
36
+ documentation_uri: https://joshuay03.github.io/red-black-tree/
37
+ source_code_uri: https://github.com/joshuay03/red-black-tree
38
+ changelog_uri: https://github.com/joshuay03/red-black-tree/blob/main/CHANGELOG.md
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 3.0.0
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubygems_version: 3.5.15
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: Red-Black Tree Data Structure for Ruby
58
+ test_files: []