@@ -130,36 +130,9 @@ def _insert_repair(self) -> None:
130
130
uncle = self .parent .sibling
131
131
if color (uncle ) == 0 :
132
132
coverageList .append (5 )
133
- if self .is_left () and self .parent .is_right ():
134
- coverageList .append (6 )
135
- self .parent .rotate_right ()
136
- if self .right :
137
- coverageList .append (7 )
138
- self .right ._insert_repair ()
139
- elif self .is_right () and self .parent .is_left ():
140
- coverageList .append (8 )
141
- self .parent .rotate_left ()
142
- if self .left :
143
- coverageList .append (9 )
144
- self .left ._insert_repair ()
145
- elif self .is_left ():
146
- coverageList .append (10 )
147
- if self .grandparent :
148
- coverageList .append (11 )
149
- self .grandparent .rotate_right ()
150
- self .parent .color = 0
151
- if self .parent .right :
152
- coverageList .append (12 )
153
- self .parent .right .color = 1
154
- else :
155
- coverageList .append (13 )
156
- if self .grandparent :
157
- coverageList .append (14 )
158
- self .grandparent .rotate_left ()
159
- self .parent .color = 0
160
- if self .parent .left :
161
- coverageList .append (15 )
162
- self .parent .left .color = 1
133
+ # There are four separate cases when the uncle is black,
134
+ # handled in a separate function with explanations
135
+ self ._insert_case_handler ()
163
136
else :
164
137
coverageList .append (16 )
165
138
self .parent .color = 0
@@ -169,6 +142,81 @@ def _insert_repair(self) -> None:
169
142
self .grandparent .color = 1
170
143
self .grandparent ._insert_repair ()
171
144
145
+ def _insert_case_handler (self ) -> None :
146
+ """ When inserting into a red-black tree and finding that the uncle
147
+ of the new node is black, there are four separate cases which
148
+ must be handled differently in order to rebalance correctly.
149
+ Two of them require further traversal, calling insert_repair again.
150
+ """
151
+ # Parent right, me left.
152
+ # Rotate parent right and insert_repair again (now right-right case).
153
+ if self .parent .is_right () and self .is_left ():
154
+ self ._insert_case_right_left ()
155
+ # Parent left, me right.
156
+ # Rotate parent left and insert_repair again (now left-left case).
157
+ elif self .parent .is_left () and self .is_right ():
158
+ self ._insert_case_left_right ()
159
+ # Parent left, me left.
160
+ # Rotate grandparent and recolour -> done.
161
+ elif self .is_left ():
162
+ self ._insert_case_left_left ()
163
+ # Parent right, me right.
164
+ # Rotate grandparent and recolour -> done.
165
+ else :
166
+ self ._insert_case_right_right ()
167
+
168
+ def _insert_case_right_right (self ) -> None :
169
+ """Parent is a right child, node is a right child.
170
+ Rotate grandparent left and swap colours of grandparent
171
+ and parent. Then we are balanced again.
172
+ """
173
+ coverageList .append (13 )
174
+ if self .grandparent :
175
+ coverageList .append (14 )
176
+ self .grandparent .rotate_left ()
177
+ self .parent .color = 0
178
+ if self .parent .left :
179
+ coverageList .append (15 )
180
+ self .parent .left .color = 1
181
+
182
+ def _insert_case_left_left (self ) -> None :
183
+ """Parent is a left child, node is a left child.
184
+ Rotate grandparent right and swap colours of grandparent
185
+ and parent. Then we are balanced again.
186
+ """
187
+ coverageList .append (10 )
188
+ if self .grandparent :
189
+ coverageList .append (11 )
190
+ self .grandparent .rotate_right ()
191
+ self .parent .color = 0
192
+ if self .parent .right :
193
+ coverageList .append (12 )
194
+ self .parent .right .color = 1
195
+
196
+ def _insert_case_right_left (self ) -> None :
197
+ """ Parent is a right child, node is a left child.
198
+ Must rotate parent right so that node becomes
199
+ its parent and both are right children, then we can apply
200
+ right-right case.
201
+ """
202
+ coverageList .append (6 )
203
+ self .parent .rotate_right ()
204
+ if self .right :
205
+ coverageList .append (7 )
206
+ self .right ._insert_repair ()
207
+
208
+ def _insert_case_left_right (self ) -> None :
209
+ """ Parent is a left child, node is a right child.
210
+ Must rotate parent left so that node becomes
211
+ its parent and both are left children, then we can apply
212
+ left-left case.
213
+ """
214
+ coverageList .append (8 )
215
+ self .parent .rotate_left ()
216
+ if self .left :
217
+ coverageList .append (9 )
218
+ self .left ._insert_repair ()
219
+
172
220
def remove (self , label : int ) -> RedBlackTree :
173
221
"""Remove label from this tree."""
174
222
if self .label == label :
0 commit comments