Commit 16c58ab9738f91d021a8685184054c4270c32f47
1 parent
5fd8c71f
change all the rebalance code to be macros
Showing
2 changed files
with
164 additions
and
177 deletions
... | ... | @@ -41,10 +41,10 @@ |
41 | 41 | |
42 | 42 | #define TR_TREE_GRANDPARENT(node) (TR_TREE_PARENT((node))->parent) |
43 | 43 | |
44 | -#define TR_TREE_UNCLE(node) \ | |
45 | - ((node)->parent == (node)->parent->parent->left? \ | |
46 | - (node)->parent->parent->right: \ | |
47 | - (node)->parent->parent->left) | |
44 | +#define TR_TREE_UNCLE(node) \ | |
45 | + ((node)->parent == (node)->parent->parent->left \ | |
46 | + ? (node)->parent->parent->right \ | |
47 | + : (node)->parent->parent->left) | |
48 | 48 | |
49 | 49 | #define TR_TREE_REPLACE_NODE(root, node1, node2) \ |
50 | 50 | if (NULL != (node1)->parent) { \ |
... | ... | @@ -89,16 +89,21 @@ |
89 | 89 | |
90 | 90 | typedef enum {rbBlack=1, rbRed=2} TR_rbColor; |
91 | 91 | |
92 | -#define TR_TREE_NODE_BLACK(node) (NULL == (node) || rbBlack == (node)->color) | |
93 | -#define TR_TREE_NODE_RED(node) (NULL == (node) || rbRed == (node)->color) | |
94 | -#define TR_TREE_NODE_STRICT_BLACK(node) (NULL != (node) && rbBlack == (node)->color) | |
95 | -#define TR_TREE_NODE_STRICT_RED(node) (NULL != (node) && rbRed == (node)->color) | |
92 | +#define TR_TREE_NODE_BLACK(node) \ | |
93 | + (NULL == (node) || rbBlack == (node)->color) | |
94 | +#define TR_TREE_NODE_RED(node) \ | |
95 | + (NULL == (node) || rbRed == (node)->color) | |
96 | +#define TR_TREE_NODE_STRICT_BLACK(node) \ | |
97 | + (NULL != (node) && rbBlack == (node)->color) | |
98 | +#define TR_TREE_NODE_STRICT_RED(node) \ | |
99 | + (NULL != (node) && rbRed == (node)->color) | |
96 | 100 | |
97 | 101 | #define TR_TREE_INORDER_SUCC(node, succ) \ |
98 | 102 | succ = (node)->right; \ |
99 | 103 | while (NULL != succ->left) { \ |
100 | 104 | succ = succ->left; \ |
101 | 105 | } |
106 | + | |
102 | 107 | /* |
103 | 108 | * Find data in a tree. |
104 | 109 | * Attention: This will change node, so normally you need to copy |
... | ... | @@ -125,6 +130,151 @@ typedef enum {rbBlack=1, rbRed=2} TR_rbColor; |
125 | 130 | } \ |
126 | 131 | } |
127 | 132 | |
133 | +#define TR_TREE_BALANCE_DELETE_CASE1(node) \ | |
134 | + if (NULL == TR_TREE_PARENT((node))) { \ | |
135 | + break; \ | |
136 | + } | |
137 | + | |
138 | +#define TR_TREE_BALANCE_DELETE_CASE2(root, node, sibling) \ | |
139 | + if (NULL != (sibling) && rbRed == (sibling)->color) { \ | |
140 | + (node)->parent->color = rbRed; \ | |
141 | + (sibling)->color = rbBlack; \ | |
142 | + if (NULL != (node)->parent->right \ | |
143 | + && (node) != (node)->parent->right) { \ | |
144 | + TR_TREE_ROTATE(left, (root), (node)->parent); \ | |
145 | + } else { \ | |
146 | + TR_TREE_ROTATE(right, (root), (node)->parent); \ | |
147 | + } \ | |
148 | + (sibling) = TR_TREE_SIBLING((node)); \ | |
149 | + } | |
150 | + | |
151 | +#define TR_TREE_BALANCE_DELETE_CASE34(root, node, sibling) \ | |
152 | + if (NULL == (sibling) \ | |
153 | + || (rbBlack == (sibling)->color \ | |
154 | + && TR_TREE_NODE_BLACK((sibling)->left) \ | |
155 | + && TR_TREE_NODE_BLACK((sibling)->right))) { \ | |
156 | + if (NULL != (sibling)) { \ | |
157 | + (sibling)->color = rbRed; \ | |
158 | + } \ | |
159 | + if (rbBlack == (node)->parent->color) { \ | |
160 | + (node) = (node)->parent; \ | |
161 | + continue; \ | |
162 | + } else { \ | |
163 | + (node)->parent->color = rbBlack; \ | |
164 | + break; \ | |
165 | + } \ | |
166 | + } | |
167 | + | |
168 | +/* | |
169 | + * this if statement is trivial, | |
170 | + * due to case 2 (even though case 2 changed the sibling to a | |
171 | + * sibling's child, | |
172 | + * the sibling's child can't be red, since no red parent can | |
173 | + * have a red child). | |
174 | + * | |
175 | + * the following statements just force the red to be on the | |
176 | + * left of the left of the parent, | |
177 | + * or right of the right, so case 6 will rotate correctly. | |
178 | + */ | |
179 | +#define TR_TREE_BALANCE_DELETE_CASE5(root, node, sibling) \ | |
180 | + if (NULL != (sibling) && rbBlack == (sibling)->color) { \ | |
181 | + if ((node) == (node)->parent->left \ | |
182 | + && TR_TREE_NODE_BLACK((sibling)->right) \ | |
183 | + && TR_TREE_NODE_STRICT_RED((sibling)->left)) { \ | |
184 | + (sibling)->color = rbRed; \ | |
185 | + (sibling)->left->color = rbBlack; \ | |
186 | + TR_TREE_ROTATE(right, (root), (sibling)); \ | |
187 | + } else if ((node) == (node)->parent->right \ | |
188 | + && TR_TREE_NODE_BLACK((sibling)->left) \ | |
189 | + && TR_TREE_NODE_STRICT_RED((sibling)->right)) { \ | |
190 | + (sibling)->color = rbRed; \ | |
191 | + (sibling)->right->color = rbBlack; \ | |
192 | + TR_TREE_ROTATE(left, (root), (sibling)); \ | |
193 | + } \ | |
194 | + (sibling) = TR_TREE_SIBLING((node)); \ | |
195 | + } | |
196 | + | |
197 | +#define TR_TREE_BALANCE_DELETE_CASE6(root, node, sibling) \ | |
198 | + if (NULL != (sibling)) { \ | |
199 | + (sibling)->color = (node)->parent->color; \ | |
200 | + } \ | |
201 | + if (NULL != (node) && NULL != (node)->parent) { \ | |
202 | + (node)->parent->color = rbBlack; \ | |
203 | + if (NULL != (node)->parent->right \ | |
204 | + && (node) != (node)->parent->right) { \ | |
205 | + if (NULL != (sibling)->right) { \ | |
206 | + (sibling)->right->color = rbBlack; \ | |
207 | + } \ | |
208 | + TR_TREE_ROTATE(left, (root), (node)->parent); \ | |
209 | + } else { \ | |
210 | + if (NULL != (sibling)->left) { \ | |
211 | + (sibling)->left->color = rbBlack; \ | |
212 | + } \ | |
213 | + TR_TREE_ROTATE(right, (root), (node)->parent); \ | |
214 | + } \ | |
215 | + } | |
216 | + | |
217 | +#define TR_TREE_BALANCE_DELETE(root, node, sibling) \ | |
218 | + while(1) { \ | |
219 | + TR_TREE_BALANCE_DELETE_CASE1((node)) \ | |
220 | + TR_TREE_BALANCE_DELETE_CASE2((root), (node), (sibling)) \ | |
221 | + TR_TREE_BALANCE_DELETE_CASE34((root), (node), (sibling)) \ | |
222 | + TR_TREE_BALANCE_DELETE_CASE5((root), (node), (sibling)) \ | |
223 | + TR_TREE_BALANCE_DELETE_CASE6((root), (node), (sibling)) \ | |
224 | + break; \ | |
225 | + } | |
226 | + | |
227 | +#define TR_TREE_BALANCE_INSERT_CASE1(node) \ | |
228 | + if (NULL == TR_TREE_PARENT((node))) { \ | |
229 | + (node)->color = rbBlack; \ | |
230 | + break; \ | |
231 | + } | |
232 | + | |
233 | +#define TR_TREE_BALANCE_INSERT_CASE2(node) \ | |
234 | + if (rbBlack == (node)->parent->color) { \ | |
235 | + break; \ | |
236 | + } | |
237 | + | |
238 | +#define TR_TREE_BALANCE_INSERT_CASE3(node) \ | |
239 | + if (NULL != TR_TREE_UNCLE(node) \ | |
240 | + && rbRed == TR_TREE_UNCLE(node)->color) { \ | |
241 | + (node)->parent->color = rbBlack; \ | |
242 | + TR_TREE_UNCLE(node)->color = rbBlack; \ | |
243 | + (node)->parent->parent->color = rbRed; \ | |
244 | + (node) = (node)->parent->parent; \ | |
245 | + continue; \ | |
246 | + } | |
247 | + | |
248 | +#define TR_TREE_BALANCE_INSERT_CASE4(root, node) \ | |
249 | + if ((node) == (node)->parent->right \ | |
250 | + && (node)->parent == (node)->parent->parent->left) { \ | |
251 | + TR_TREE_ROTATE(left, (root), (node)->parent); \ | |
252 | + (node) = (node)->left; \ | |
253 | + } else if ((node) == (node)->parent->left \ | |
254 | + && (node)->parent == (node)->parent->parent->right) { \ | |
255 | + TR_TREE_ROTATE(right, (root), (node)->parent); \ | |
256 | + (node) = (node)->right; \ | |
257 | + } | |
258 | + | |
259 | +#define TR_TREE_BALANCE_INSERT_CASE5(root, node) \ | |
260 | + (node)->parent->color = rbBlack; \ | |
261 | + (node)->parent->parent->color = rbRed; \ | |
262 | + if ((node) == (node)->parent->left) { \ | |
263 | + TR_TREE_ROTATE(right, (root), (node)->parent->parent); \ | |
264 | + } else { \ | |
265 | + TR_TREE_ROTATE(left, (root), (node)->parent->parent); \ | |
266 | + } | |
267 | + | |
268 | +#define TR_TREE_BALANCE_INSERT(root, node) \ | |
269 | + while (1) { \ | |
270 | + TR_TREE_BALANCE_INSERT_CASE1((node)) \ | |
271 | + TR_TREE_BALANCE_INSERT_CASE2((node)) \ | |
272 | + TR_TREE_BALANCE_INSERT_CASE3((node)) \ | |
273 | + TR_TREE_BALANCE_INSERT_CASE4((root), (node)) \ | |
274 | + TR_TREE_BALANCE_INSERT_CASE5((root), (node)) \ | |
275 | + break; \ | |
276 | + } | |
277 | + | |
128 | 278 | #endif // __TR_TREE_MACROS_H__ |
129 | 279 | |
130 | 280 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -131,8 +131,6 @@ insertElement(struct memSegment ** tree, struct memSegment * element) |
131 | 131 | { |
132 | 132 | struct memSegment * node = *tree; |
133 | 133 | struct memSegment * new_node = NULL; |
134 | - struct memSegment * u; | |
135 | - struct memSegment * g; | |
136 | 134 | int found; |
137 | 135 | |
138 | 136 | element->next = NULL; |
... | ... | @@ -173,63 +171,10 @@ insertElement(struct memSegment ** tree, struct memSegment * element) |
173 | 171 | } |
174 | 172 | } |
175 | 173 | |
176 | - if (NULL != new_node) { | |
177 | - /* | |
178 | - * handle reballancing rb style | |
179 | - */ | |
180 | - while (1) { | |
181 | - // case 1 | |
182 | - if (node->parent == NULL) { | |
183 | - node->color = rbBlack; | |
184 | - // we're done.... :) | |
185 | - break; | |
186 | - } | |
187 | - | |
188 | - // case 2 | |
189 | - if (node->parent->color == rbBlack) { | |
190 | - // Tree is still valid ... wow, again we're done... :) | |
191 | - break; | |
192 | - } | |
193 | - | |
194 | - // case 3 | |
195 | - u = TR_TREE_UNCLE(node); | |
196 | - g = TR_TREE_GRANDPARENT(node); | |
197 | - | |
198 | - if (u != NULL && u->color == rbRed) { | |
199 | - node->parent->color = rbBlack; | |
200 | - u->color = rbBlack; | |
201 | - g->color = rbRed; | |
202 | - | |
203 | - node = g; | |
204 | - continue; | |
205 | - } | |
206 | - | |
207 | - // case 4 | |
208 | - if (node == node->parent->right && node->parent == g->left) { | |
209 | - TR_TREE_ROTATE(left, tree, node->parent); | |
210 | - node = node->left; | |
211 | - } else if (node == node->parent->left && node->parent == g->right) { | |
212 | - | |
213 | - TR_TREE_ROTATE(right, tree, node->parent); | |
214 | - node = node->right; | |
215 | - } | |
216 | - | |
217 | - // case 5 | |
218 | - g = TR_TREE_GRANDPARENT(node); | |
219 | - | |
220 | - node->parent->color = rbBlack; | |
221 | - g->color = rbRed; | |
222 | - | |
223 | - if (node == node->parent->left) { | |
224 | - TR_TREE_ROTATE(right, tree, g); | |
225 | - } else { | |
226 | - TR_TREE_ROTATE(left, tree, g); | |
227 | - } | |
228 | - | |
229 | - // we're done.. | |
230 | - break; | |
231 | - } | |
232 | - } | |
174 | + /* | |
175 | + * handle reballancing rb style | |
176 | + */ | |
177 | + TR_TREE_BALANCE_INSERT(tree, node); | |
233 | 178 | |
234 | 179 | return new_node; |
235 | 180 | } |
... | ... | @@ -345,116 +290,8 @@ deleteElement(struct memSegment ** tree, size_t size) |
345 | 290 | return del_node; |
346 | 291 | } |
347 | 292 | |
348 | - // delete and rb rebalance... | |
349 | - while(1) { | |
350 | - // case 1 | |
351 | - if (NULL == node->parent) { | |
352 | - // done again | |
353 | - break; | |
354 | - } | |
355 | - | |
356 | - // case 2 | |
357 | - s = TR_TREE_SIBLING(node); | |
358 | - | |
359 | - if (NULL != s && s->color == rbRed) { | |
360 | - node->parent->color = rbRed; | |
361 | - s->color = rbBlack; | |
362 | - | |
363 | - /* | |
364 | - * detect which child we are...assumption | |
365 | - * if we are not parent->right and parent->right is not | |
366 | - * null we must be left, even if its set to NULL previously | |
367 | - */ | |
368 | - if (NULL != node->parent->right && node != node->parent->right) { | |
369 | - TR_TREE_ROTATE(left, tree, node->parent); | |
370 | - } else { | |
371 | - TR_TREE_ROTATE(right, tree, node->parent); | |
372 | - } | |
373 | - } | |
374 | - | |
375 | - s = TR_TREE_SIBLING(node); | |
376 | - // case 3 / 4 | |
377 | - if (NULL == s || ((s->color == rbBlack) && | |
378 | - (NULL == s->left || s->left->color == rbBlack) && | |
379 | - (NULL == s->right || s->right->color == rbBlack))) { | |
380 | - | |
381 | - if (NULL != s) { | |
382 | - s->color = rbRed; | |
383 | - } | |
384 | - | |
385 | - if (node->parent->color == rbBlack) { | |
386 | - // case 3 | |
387 | - node = node->parent; | |
388 | - continue; | |
389 | - } else { | |
390 | - // case 4 | |
391 | - node->parent->color = rbBlack; | |
392 | - // and done again... | |
393 | - break; | |
394 | - } | |
395 | - } | |
396 | - | |
397 | - // case 5 | |
398 | - if (NULL != s && s->color == rbBlack) { | |
399 | - // this if statement is trivial, | |
400 | - // due to case 2 (even though case 2 changed the sibling to a | |
401 | - // sibling's child, | |
402 | - // the sibling's child can't be red, since no red parent can | |
403 | - // have a red child). | |
404 | - // | |
405 | - // the following statements just force the red to be on the | |
406 | - // left of the left of the parent, | |
407 | - // or right of the right, so case 6 will rotate correctly. | |
408 | - if ((node == node->parent->left) && | |
409 | - (NULL == s->right || s->right->color == rbBlack) && | |
410 | - (NULL != s->left && s->left->color == rbRed)) { | |
411 | - | |
412 | - // this last test is trivial too due to cases 2-4. | |
413 | - s->color = rbRed; | |
414 | - s->left->color = rbBlack; | |
415 | - | |
416 | - TR_TREE_ROTATE(right, tree, s); | |
417 | - } else if ((node == node->parent->right) && | |
418 | - (NULL == s->left || s->left->color == rbBlack) && | |
419 | - (NULL != s->right && s->right->color == rbRed)) { | |
420 | - // this last test is trivial too due to cases 2-4. | |
421 | - s->color = rbRed; | |
422 | - s->right->color = rbBlack; | |
423 | - | |
424 | - TR_TREE_ROTATE(left, tree, s); | |
425 | - } | |
426 | - } | |
427 | - | |
428 | - s = TR_TREE_SIBLING(node); | |
429 | - // case 6 | |
430 | - if (NULL != s) { | |
431 | - s->color = node->parent->color; | |
432 | - } | |
433 | - | |
434 | - if (NULL != node && NULL != node->parent) { | |
435 | - node->parent->color = rbBlack; | |
436 | - | |
437 | - /* | |
438 | - * detect which child we are...assumption | |
439 | - * if we are not parent->right and parent->right is not | |
440 | - * null we must be left, even if its set to NULL previously | |
441 | - */ | |
442 | - if (NULL != node->parent->right && node != node->parent->right) { | |
443 | - if (NULL != s->right) { | |
444 | - s->right->color = rbBlack; | |
445 | - } | |
446 | - TR_TREE_ROTATE(left, tree, node->parent); | |
447 | - } else { | |
448 | - if (NULL != s->left) { | |
449 | - s->left->color = rbBlack; | |
450 | - } | |
451 | - TR_TREE_ROTATE(right, tree, node->parent); | |
452 | - } | |
453 | - } | |
454 | - | |
455 | - // done... | |
456 | - break; | |
457 | - } | |
293 | + s = TR_TREE_SIBLING(node); | |
294 | + TR_TREE_BALANCE_DELETE(tree, node, s); | |
458 | 295 | |
459 | 296 | return del_node; |
460 | 297 | } | ... | ... |
Please
register
or
login
to post a comment