red-black-tree 0.1.5 → 0.1.6

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
  SHA256:
3
- metadata.gz: b90594d4e04c47851ed0eaa18f0f517c37081a9c52c21ae5d4af66b142e2fdb1
4
- data.tar.gz: de26391d21001786ee4f39859ef248985bbb5ca9750187f069219b3fdd72813e
3
+ metadata.gz: da41036d61ffc0739627740b631dbb00df76ee87a5db6145ad508569552703c3
4
+ data.tar.gz: 99172cd947f7714788dadd94068ff637bdfa510ae78367a4689a892dc4ad1a05
5
5
  SHA512:
6
- metadata.gz: df049ff727c8918d99e255e44977281e378269620d04dbb16e3d6d1990e72416d85c1c42c7815de67d0c2f1366c68db463587d4cdfe56213cc6f45e4476f6648
7
- data.tar.gz: dea0e150ee92555bff5af6e81cf81e4df9f75326a3c7e8bfa907c24b17dfa42f13548f113d9ec0b3448127a92794a0059701136eda88cd7c6fe0c44f5a75bfe9
6
+ metadata.gz: 96e4b84d481b71cf8f3e45b728d19c1417f50c68ea9a9b8acdbd35a3514c8ab154df42ef7b3542ff0655e45c76a2f39b2a4a7ad6131a2c238fd7b126bddc29bd
7
+ data.tar.gz: 54a7743f84d5748e830dee7ed27c66f34c9517d4977b496c74cc6aa194b0fbef175f5ad7bd3d7420ce64f68298ff4bf529b9d1664966c94007db5fd1cc76d35d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.1.6] - 2025-01-01
4
+
5
+ - Prefer node deletion over data swapping
6
+
3
7
  ## [0.1.5] - 2024-10-28
4
8
 
5
9
  - Alias `RedBlackTree#search` as `RedBlackTree#find`
data/README.md CHANGED
@@ -83,20 +83,20 @@ Benchmark.ips do |x|
83
83
  x.compare!
84
84
  end
85
85
 
86
- #=> ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin24]
86
+ #=> ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +PRISM [arm64-darwin24]
87
87
  #=> Warming up --------------------------------------
88
88
  #=> RedBlackTree 1.000 i/100ms
89
89
  #=> Array (gradual sort) 1.000 i/100ms
90
- #=> Array (single sort) 78.000 i/100ms
90
+ #=> Array (single sort) 100.000 i/100ms
91
91
  #=> Calculating -------------------------------------
92
- #=> RedBlackTree 5.4170.0%) i/s (184.61 ms/i) - 28.000 in 5.172532s
93
- #=> Array (gradual sort) 0.268 (± 0.0%) i/s (3.74 s/i) - 2.000 in 7.473005s
94
- #=> Array (single sort) 768.691 (± 2.2%) i/s (1.30 ms/i) - 3.900k in 5.076337s
92
+ #=> RedBlackTree 16.6846.0%) i/s (59.94 ms/i) - 84.000 in 5.053688s
93
+ #=> Array (gradual sort) 0.270 (± 0.0%) i/s (3.71 s/i) - 2.000 in 7.418650s
94
+ #=> Array (single sort) 1.006k (± 2.4%) i/s (994.28 μs/i) - 5.100k in 5.073834s
95
95
  #=>
96
96
  #=> Comparison:
97
- #=> Array (single sort): 768.7 i/s
98
- #=> RedBlackTree: 5.4 i/s - 141.91x slower
99
- #=> Array (gradual sort): 0.3 i/s - 2872.03x slower
97
+ #=> Array (single sort): 1005.8 i/s
98
+ #=> RedBlackTree: 16.7 i/s - 60.28x slower
99
+ #=> Array (gradual sort): 0.3 i/s - 3729.44x slower
100
100
  ```
101
101
 
102
102
  ### Sort and search 10,000 elements
@@ -153,34 +153,34 @@ Benchmark.ips do |x|
153
153
  x.compare!
154
154
  end
155
155
 
156
- #=> ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [arm64-darwin24]
156
+ #=> ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +PRISM [arm64-darwin24]
157
157
  #=> Warming up --------------------------------------
158
- #=> RedBlackTree#search 1.000 i/100ms
158
+ #=> RedBlackTree#search 3.000 i/100ms
159
159
  #=> Array#find (gradual sort)
160
160
  #=> 1.000 i/100ms
161
161
  #=> Array#find (single sort)
162
- #=> 69.000 i/100ms
162
+ #=> 95.000 i/100ms
163
163
  #=> Array#bsearch (gradual sort)
164
164
  #=> 1.000 i/100ms
165
165
  #=> Array#bsearch (single sort)
166
- #=> 89.000 i/100ms
166
+ #=> 108.000 i/100ms
167
167
  #=> Calculating -------------------------------------
168
- #=> RedBlackTree#search 12.9260.0%) i/s (77.36 ms/i) - 65.000 in 5.030736s
168
+ #=> RedBlackTree#search 42.8504.7%) i/s (23.34 ms/i) - 216.000 in 5.049896s
169
169
  #=> Array#find (gradual sort)
170
- #=> 0.262 (± 0.0%) i/s (3.81 s/i) - 2.000 in 7.623953s
170
+ #=> 0.274 (± 0.0%) i/s (3.65 s/i) - 2.000 in 7.302412s
171
171
  #=> Array#find (single sort)
172
- #=> 690.6311.0%) i/s (1.45 ms/i) - 3.519k in 5.095823s
172
+ #=> 935.4922.7%) i/s (1.07 ms/i) - 4.750k in 5.081415s
173
173
  #=> Array#bsearch (gradual sort)
174
- #=> 0.267 (± 0.0%) i/s (3.75 s/i) - 2.000 in 7.492482s
174
+ #=> 0.275 (± 0.0%) i/s (3.63 s/i) - 2.000 in 7.269027s
175
175
  #=> Array#bsearch (single sort)
176
- #=> 895.4131.7%) i/s (1.12 ms/i) - 4.539k in 5.070590s
176
+ #=> 1.104k2.0%) i/s (905.52 μs/i) - 5.616k in 5.087395s
177
177
  #=>
178
178
  #=> Comparison:
179
- #=> Array#bsearch (single sort): 895.4 i/s
180
- #=> Array#find (single sort): 690.6 i/s - 1.30x slower
181
- #=> RedBlackTree#search: 12.9 i/s - 69.27x slower
182
- #=> Array#bsearch (gradual sort): 0.3 i/s - 3354.39x slower
183
- #=> Array#find (gradual sort): 0.3 i/s - 3412.57x slower
179
+ #=> Array#bsearch (single sort): 1104.3 i/s
180
+ #=> Array#find (single sort): 935.5 i/s - 1.18x slower
181
+ #=> RedBlackTree#search: 42.9 i/s - 25.77x slower
182
+ #=> Array#bsearch (gradual sort): 0.3 i/s - 4013.67x slower
183
+ #=> Array#find (gradual sort): 0.3 i/s - 4031.85x slower
184
184
  ```
185
185
 
186
186
  ## WIP Features
@@ -145,21 +145,38 @@ class RedBlackTree
145
145
  original_node = node
146
146
 
147
147
  if node.children_are_valid?
148
+ is_root = is_root? node
149
+
148
150
  successor = node.left
149
151
  successor = successor.left until successor.left.leaf?
150
- node.swap_data_with! successor
152
+ node.swap_colour_with! successor
153
+ node.swap_position_with! successor
154
+ node.swap_position_with! LeafNode.new
155
+
156
+ @root = successor if is_root
157
+
158
+ original_node.validate_free!
151
159
 
152
- return delete! successor
160
+ decrement_size!
161
+ update_left_most_node!
162
+
163
+ return self
153
164
  elsif node.single_child_is_valid?
154
165
  is_root = is_root? node
155
166
 
156
167
  valid_child = node.children.find(&:valid?)
157
- node.swap_data_with! valid_child
158
- node.black!
168
+ valid_child.black!
169
+ node.swap_position_with! valid_child
170
+ node.swap_position_with! LeafNode.new
171
+
172
+ @root = valid_child if is_root
173
+
174
+ original_node.validate_free!
159
175
 
160
- @root = node if is_root
176
+ decrement_size!
177
+ update_left_most_node!
161
178
 
162
- return delete! valid_child
179
+ return self
163
180
  elsif node.children_are_leaves?
164
181
  if is_root? node
165
182
  @root = nil
@@ -7,7 +7,7 @@ class RedBlackTree
7
7
  case direction
8
8
  when Node::LEFT then @left
9
9
  when Node::RIGHT then @right
10
- else raise ArgumentError, "Direction must be one of #{Implementation::DIRECTIONS}"
10
+ else raise ArgumentError, "Direction must be one of #{Implementation::DIRECTIONS}, got #{direction}"
11
11
  end
12
12
  end
13
13
 
@@ -15,7 +15,7 @@ class RedBlackTree
15
15
  case direction
16
16
  when Node::LEFT then @left = node
17
17
  when Node::RIGHT then @right = node
18
- else raise ArgumentError, "Direction must be one of #{Implementation::DIRECTIONS}"
18
+ else raise ArgumentError, "Direction must be one of #{Implementation::DIRECTIONS}, got #{direction}"
19
19
  end
20
20
  end
21
21
  end
@@ -125,12 +125,6 @@ class RedBlackTree
125
125
  raise StructuralError, "Node is still chained to #{anchors.join(", ")}"
126
126
  end
127
127
 
128
- def swap_data_with! other_node
129
- temp_data = @data
130
- @data = other_node.data
131
- other_node.data = temp_data
132
- end
133
-
134
128
  def swap_colour_with! other_node
135
129
  temp_colour = @colour
136
130
 
@@ -148,27 +142,47 @@ class RedBlackTree
148
142
  def swap_position_with! other_node
149
143
  self_position = position
150
144
  other_position = other_node.position
145
+ opp_other_position = opposite_direction other_position if other_position
151
146
 
152
147
  if other_node.parent.object_id == self.object_id
153
148
  self[other_position] = other_node[other_position]
154
149
  other_node[other_position] = self
155
150
 
151
+ self[other_position].parent = self
156
152
  other_node.parent = @parent
153
+
154
+ @parent[self_position] = other_node if self_position
157
155
  @parent = other_node
158
- elsif other_node.object_id == @parent.object_id
159
- other_node[self_position] = self[self_position]
160
- self[self_position] = other_node
161
156
 
162
- temp_parent = other_node.parent
163
- other_node.parent = self
164
- @parent = temp_parent
157
+ temp_node = self[opp_other_position]
158
+ self[opp_other_position] = other_node[opp_other_position]
159
+ other_node[opp_other_position] = temp_node
160
+
161
+ self[opp_other_position].parent = self
162
+ other_node[opp_other_position].parent = other_node
163
+ elsif other_node.object_id == @parent.object_id
164
+ other_node.swap_position_with! self
165
165
  else
166
166
  other_node.parent[other_position] = self if other_node.parent
167
167
  @parent[self_position] = other_node if @parent
168
168
 
169
- temp_parent = other_node.parent
169
+ temp_node = other_node.parent
170
170
  other_node.parent = @parent
171
- @parent = temp_parent
171
+ @parent = temp_node
172
+
173
+ temp_node = other_node.left
174
+ other_node.left = @left
175
+ @left = temp_node
176
+
177
+ @left.parent = self if @left
178
+ other_node.left.parent = other_node if other_node.left
179
+
180
+ temp_node = other_node.right
181
+ other_node.right = @right
182
+ @right = temp_node
183
+
184
+ @right.parent = self if @right
185
+ other_node.right.parent = other_node if other_node.right
172
186
  end
173
187
  end
174
188
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class RedBlackTree
4
- VERSION = "0.1.5"
4
+ VERSION = "0.1.6"
5
5
  end
metadata CHANGED
@@ -1,16 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: red-black-tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Young
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-10-27 00:00:00.000000000 Z
10
+ date: 2025-01-01 00:00:00.000000000 Z
12
11
  dependencies: []
13
- description:
14
12
  email:
15
13
  - djry1999@gmail.com
16
14
  executables: []
@@ -37,7 +35,6 @@ metadata:
37
35
  documentation_uri: https://joshuay03.github.io/red-black-tree/
38
36
  source_code_uri: https://github.com/joshuay03/red-black-tree
39
37
  changelog_uri: https://github.com/joshuay03/red-black-tree/blob/main/CHANGELOG.md
40
- post_install_message:
41
38
  rdoc_options: []
42
39
  require_paths:
43
40
  - lib
@@ -52,8 +49,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
52
49
  - !ruby/object:Gem::Version
53
50
  version: '0'
54
51
  requirements: []
55
- rubygems_version: 3.5.16
56
- signing_key:
52
+ rubygems_version: 3.6.2
57
53
  specification_version: 4
58
54
  summary: Red-Black Tree Data Structure for Ruby
59
55
  test_files: []