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,10 +41,10 @@ | ||
| 41 | 41 | ||
| 42 | #define TR_TREE_GRANDPARENT(node) (TR_TREE_PARENT((node))->parent) | 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 | #define TR_TREE_REPLACE_NODE(root, node1, node2) \ | 49 | #define TR_TREE_REPLACE_NODE(root, node1, node2) \ |
| 50 | if (NULL != (node1)->parent) { \ | 50 | if (NULL != (node1)->parent) { \ |
| @@ -89,16 +89,21 @@ | @@ -89,16 +89,21 @@ | ||
| 89 | 89 | ||
| 90 | typedef enum {rbBlack=1, rbRed=2} TR_rbColor; | 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 | #define TR_TREE_INORDER_SUCC(node, succ) \ | 101 | #define TR_TREE_INORDER_SUCC(node, succ) \ |
| 98 | succ = (node)->right; \ | 102 | succ = (node)->right; \ |
| 99 | while (NULL != succ->left) { \ | 103 | while (NULL != succ->left) { \ |
| 100 | succ = succ->left; \ | 104 | succ = succ->left; \ |
| 101 | } | 105 | } |
| 106 | + | ||
| 102 | /* | 107 | /* |
| 103 | * Find data in a tree. | 108 | * Find data in a tree. |
| 104 | * Attention: This will change node, so normally you need to copy | 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,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 | #endif // __TR_TREE_MACROS_H__ | 278 | #endif // __TR_TREE_MACROS_H__ |
| 129 | 279 | ||
| 130 | // vim: set ts=4 sw=4: | 280 | // vim: set ts=4 sw=4: |
| @@ -131,8 +131,6 @@ insertElement(struct memSegment ** tree, struct memSegment * element) | @@ -131,8 +131,6 @@ insertElement(struct memSegment ** tree, struct memSegment * element) | ||
| 131 | { | 131 | { |
| 132 | struct memSegment * node = *tree; | 132 | struct memSegment * node = *tree; |
| 133 | struct memSegment * new_node = NULL; | 133 | struct memSegment * new_node = NULL; |
| 134 | - struct memSegment * u; | ||
| 135 | - struct memSegment * g; | ||
| 136 | int found; | 134 | int found; |
| 137 | 135 | ||
| 138 | element->next = NULL; | 136 | element->next = NULL; |
| @@ -173,63 +171,10 @@ insertElement(struct memSegment ** tree, struct memSegment * element) | @@ -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 | return new_node; | 179 | return new_node; |
| 235 | } | 180 | } |
| @@ -345,116 +290,8 @@ deleteElement(struct memSegment ** tree, size_t size) | @@ -345,116 +290,8 @@ deleteElement(struct memSegment ** tree, size_t size) | ||
| 345 | return del_node; | 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 | return del_node; | 296 | return del_node; |
| 460 | } | 297 | } |
Please
register
or
login
to post a comment