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