red-black-tree 0.1.5 → 0.1.6

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
  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: []