@@ -106,27 +106,7 @@ def insert! node, target_parent = nil, direction = nil
106106 node . parent = target_parent
107107 node . red!
108108
109- while node . parent && node . parent . red? do
110- if node . parent . sibling && node . parent . sibling . red?
111- node . parent . black!
112- node . parent . sibling . black!
113- node . parent . parent . red!
114- node = node . parent . parent
115- else
116- opp_direction = node . opposite_position
117- if node . parent . position == opp_direction
118- rotate_sub_tree! node . parent , opp_direction
119- node = node [ opp_direction ]
120- end
121-
122- opp_direction = node . opposite_position
123- rotate_sub_tree! node . parent . parent , opp_direction
124- node . parent . black!
125- node . parent [ opp_direction ] . red!
126- end
127-
128- @root . black!
129- end
109+ rebalance_after_insertion! node
130110 end
131111
132112 node . validate! @root == node
@@ -153,71 +133,11 @@ def delete! node
153133 original_node = node
154134
155135 if node . children_are_valid?
156- is_root = is_root? node
157-
158- successor = node . left
159- successor = successor . left until successor . left . leaf?
160- node . swap_colour_with! successor
161- node . swap_position_with! successor
162- node . swap_position_with! LeafNode . new
163-
164- @root = successor if is_root
136+ delete_node_with_two_children! node
165137 elsif node . single_child_is_valid?
166- is_root = is_root? node
167-
168- valid_child = node . children . find ( &:valid? )
169- valid_child . black!
170- node . swap_position_with! valid_child
171- node . swap_position_with! LeafNode . new
172-
173- @root = valid_child if is_root
138+ delete_node_with_one_child! node
174139 elsif node . children_are_leaves?
175- if is_root? node
176- @root = nil
177- elsif node . red?
178- node . swap_position_with! LeafNode . new
179- else
180- loop do
181- if node . sibling && node . sibling . valid? && node . sibling . red?
182- node . parent . red!
183- node . sibling . black!
184- rotate_sub_tree! node . parent , node . position
185- end
186-
187- if node . close_nephew && node . close_nephew . valid? && node . close_nephew . red?
188- node . sibling . red! unless node . sibling . leaf?
189- node . close_nephew . black!
190- rotate_sub_tree! node . sibling , node . opposite_position
191- end
192-
193- if node . distant_nephew && node . distant_nephew . valid? && node . distant_nephew . red?
194- case node . parent . colour
195- when Node ::RED then node . sibling . red!
196- when Node ::BLACK then node . sibling . black!
197- end
198- node . parent . black!
199- node . distant_nephew . black!
200- rotate_sub_tree! node . parent , node . position
201-
202- break
203- end
204-
205- if node . parent && node . parent . red?
206- node . sibling . red! unless node . sibling . leaf?
207- node . parent . black!
208-
209- break
210- end
211-
212- if node . sibling && !node . sibling . leaf?
213- node . sibling . red!
214- end
215-
216- break unless node = node . parent
217- end
218-
219- original_node . swap_position_with! LeafNode . new
220- end
140+ delete_leaf_node! node , original_node
221141 end
222142
223143 original_node . tree = nil
@@ -270,7 +190,7 @@ def select &block
270190 #
271191 # @return [true, false]
272192 def include? data
273- !! search ( data )
193+ !search ( data ) . nil?
274194 end
275195
276196 # Traverses the tree in pre-order and yields each node.
@@ -363,8 +283,8 @@ def _search_by_data data, node
363283 return if node . nil? || node . leaf?
364284 return node if data == node . data
365285
366- mock_node = node . class . new data
367- if mock_node >= node
286+ comparison = data <=> node . data
287+ if comparison && comparison >= 0
368288 _search_by_data data , node . right
369289 else
370290 _search_by_data data , node . left
@@ -401,6 +321,105 @@ def decrement_size!
401321 @size -= 1
402322 end
403323
324+ def delete_node_with_two_children! node
325+ is_root = is_root? node
326+
327+ successor = node . left
328+ successor = successor . right until successor . right . leaf?
329+ node . swap_colour_with! successor
330+ node . swap_position_with! successor
331+ node . swap_position_with! LeafNode . new
332+
333+ @root = successor if is_root
334+ end
335+
336+ def delete_node_with_one_child! node
337+ is_root = is_root? node
338+
339+ valid_child = node . children . find ( &:valid? )
340+ valid_child . black!
341+ node . swap_position_with! valid_child
342+ node . swap_position_with! LeafNode . new
343+
344+ @root = valid_child if is_root
345+ end
346+
347+ def delete_leaf_node! node , original_node
348+ if is_root? node
349+ @root = nil
350+ elsif node . red?
351+ node . swap_position_with! LeafNode . new
352+ else
353+ rebalance_after_deletion! node
354+ original_node . swap_position_with! LeafNode . new
355+ end
356+ end
357+
358+ def rebalance_after_deletion! node
359+ loop do
360+ if node . sibling && node . sibling . valid? && node . sibling . red?
361+ node . parent . red!
362+ node . sibling . black!
363+ rotate_sub_tree! node . parent , node . position
364+ end
365+
366+ if node . close_nephew && node . close_nephew . valid? && node . close_nephew . red?
367+ node . sibling . red! unless node . sibling . leaf?
368+ node . close_nephew . black!
369+ rotate_sub_tree! node . sibling , node . opposite_position
370+ end
371+
372+ if node . distant_nephew && node . distant_nephew . valid? && node . distant_nephew . red?
373+ case node . parent . colour
374+ when Node ::RED then node . sibling . red!
375+ when Node ::BLACK then node . sibling . black!
376+ end
377+ node . parent . black!
378+ node . distant_nephew . black!
379+ rotate_sub_tree! node . parent , node . position
380+
381+ break
382+ end
383+
384+ if node . parent && node . parent . red?
385+ node . sibling . red! unless node . sibling . leaf?
386+ node . parent . black!
387+
388+ break
389+ end
390+
391+ if node . sibling && !node . sibling . leaf?
392+ node . sibling . red!
393+ end
394+
395+ break unless node = node . parent
396+ end
397+ end
398+
399+ def rebalance_after_insertion! node
400+ while node . parent && node . parent . red? do
401+ if node . parent . sibling && node . parent . sibling . red?
402+ node . parent . black!
403+ node . parent . sibling . black!
404+ node . parent . parent . red!
405+ node = node . parent . parent
406+ else
407+ opp_direction = node . opposite_position
408+ if node . parent . position == opp_direction
409+ rotate_sub_tree! node . parent , opp_direction
410+ node = node [ opp_direction ]
411+ end
412+
413+ opp_direction = node . opposite_position
414+ rotate_sub_tree! node . parent . parent , opp_direction
415+ node . parent . black!
416+ node . parent [ opp_direction ] . red!
417+ end
418+
419+ @root . black!
420+ end
421+ end
422+
404423 def update_left_most_node!
405424 unless @root
406425 @left_most_node = nil
0 commit comments