/* * Copyright (c) 2010-2017 Richard Braun. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Upstream site with license notes : * http://git.sceen.net/rbraun/librbraun.git/ */ #include #include #include #include #include #include /* * Return the index of a node in the children array of its parent. * * The parent parameter must not be NULL, and must be the parent of the * given node. */ static inline int rbtree_node_index(const struct rbtree_node *node, const struct rbtree_node *parent) { assert(parent != NULL); assert((node == NULL) || (rbtree_node_parent(node) == parent)); if (parent->children[RBTREE_LEFT] == node) { return RBTREE_LEFT; } assert(parent->children[RBTREE_RIGHT] == node); return RBTREE_RIGHT; } /* * Return the color of a node. */ static inline int rbtree_node_color(const struct rbtree_node *node) { return node->parent & RBTREE_COLOR_MASK; } /* * Return true if the node is red. */ static inline int rbtree_node_is_red(const struct rbtree_node *node) { return rbtree_node_color(node) == RBTREE_COLOR_RED; } /* * Return true if the node is black. */ static inline int rbtree_node_is_black(const struct rbtree_node *node) { return rbtree_node_color(node) == RBTREE_COLOR_BLACK; } /* * Set the parent of a node, retaining its current color. */ static inline void rbtree_node_set_parent(struct rbtree_node *node, struct rbtree_node *parent) { assert(rbtree_node_check_alignment(node)); assert(rbtree_node_check_alignment(parent)); node->parent = (uintptr_t)parent | (node->parent & RBTREE_COLOR_MASK); } /* * Set the color of a node, retaining its current parent. */ static inline void rbtree_node_set_color(struct rbtree_node *node, int color) { assert((color & ~RBTREE_COLOR_MASK) == 0); node->parent = (node->parent & RBTREE_PARENT_MASK) | color; } /* * Set the color of a node to red, retaining its current parent. */ static inline void rbtree_node_set_red(struct rbtree_node *node) { rbtree_node_set_color(node, RBTREE_COLOR_RED); } /* * Set the color of a node to black, retaining its current parent. */ static inline void rbtree_node_set_black(struct rbtree_node *node) { rbtree_node_set_color(node, RBTREE_COLOR_BLACK); } /* * Return the left-most deepest child node of the given node. */ static struct rbtree_node * rbtree_node_find_deepest(struct rbtree_node *node) { struct rbtree_node *parent; assert(node != NULL); for (;;) { parent = node; node = node->children[RBTREE_LEFT]; if (node == NULL) { node = parent->children[RBTREE_RIGHT]; if (node == NULL) { return parent; } } } } /* * Perform a tree rotation, rooted at the given node. * * The direction parameter defines the rotation direction and is either * RBTREE_LEFT or RBTREE_RIGHT. */ static void rbtree_rotate(struct rbtree *tree, struct rbtree_node *node, int direction) { struct rbtree_node *parent, *rnode; int left, right; left = direction; right = 1 - left; parent = rbtree_node_parent(node); rnode = node->children[right]; node->children[right] = rnode->children[left]; if (rnode->children[left] != NULL) { rbtree_node_set_parent(rnode->children[left], node); } rnode->children[left] = node; rbtree_node_set_parent(rnode, parent); if (unlikely(parent == NULL)) { tree->root = rnode; } else { parent->children[rbtree_node_index(node, parent)] = rnode; } rbtree_node_set_parent(node, rnode); } void rbtree_insert_rebalance(struct rbtree *tree, struct rbtree_node *parent, int index, struct rbtree_node *node) { struct rbtree_node *grand_parent, *uncle; int left, right; assert(rbtree_node_check_alignment(parent)); assert(rbtree_node_check_alignment(node)); node->parent = (uintptr_t)parent | RBTREE_COLOR_RED; node->children[RBTREE_LEFT] = NULL; node->children[RBTREE_RIGHT] = NULL; if (unlikely(parent == NULL)) { tree->root = node; } else { parent->children[index] = node; } for (;;) { if (parent == NULL) { rbtree_node_set_black(node); break; } if (rbtree_node_is_black(parent)) { break; } grand_parent = rbtree_node_parent(parent); assert(grand_parent != NULL); left = rbtree_node_index(parent, grand_parent); right = 1 - left; uncle = grand_parent->children[right]; /* * Uncle is red. Flip colors and repeat at grand parent. */ if ((uncle != NULL) && rbtree_node_is_red(uncle)) { rbtree_node_set_black(uncle); rbtree_node_set_black(parent); rbtree_node_set_red(grand_parent); node = grand_parent; parent = rbtree_node_parent(node); continue; } /* * Node is the right child of its parent. Rotate left at parent. */ if (parent->children[right] == node) { rbtree_rotate(tree, parent, left); parent = node; } /* * Node is the left child of its parent. Handle colors, rotate right * at grand parent, and leave. */ rbtree_node_set_black(parent); rbtree_node_set_red(grand_parent); rbtree_rotate(tree, grand_parent, right); break; } assert(rbtree_node_is_black(tree->root)); } void * rbtree_replace_slot(struct rbtree *tree, rbtree_slot_t slot, struct rbtree_node *node) { struct rbtree_node *parent, *prev; int index; parent = rbtree_slot_parent(slot); if (!parent) { prev = tree->root; tree->root = node; } else { index = rbtree_slot_index(slot); assert(rbtree_check_index(index)); prev = parent->children[index]; parent->children[index] = node; } assert(prev); *node = *prev; for (size_t i = 0; i < ARRAY_SIZE(node->children); i++) { if (!node->children[i]) { continue; } rbtree_node_set_parent(node->children[i], node); } return prev; } void rbtree_remove(struct rbtree *tree, struct rbtree_node *node) { struct rbtree_node *child, *parent, *brother; int color, left, right; if (node->children[RBTREE_LEFT] == NULL) { child = node->children[RBTREE_RIGHT]; } else if (node->children[RBTREE_RIGHT] == NULL) { child = node->children[RBTREE_LEFT]; } else { struct rbtree_node *successor; /* * Two-children case: replace the node with its successor. */ successor = node->children[RBTREE_RIGHT]; while (successor->children[RBTREE_LEFT] != NULL) { successor = successor->children[RBTREE_LEFT]; } color = rbtree_node_color(successor); child = successor->children[RBTREE_RIGHT]; parent = rbtree_node_parent(node); if (unlikely(parent == NULL)) { tree->root = successor; } else { parent->children[rbtree_node_index(node, parent)] = successor; } parent = rbtree_node_parent(successor); /* * Set parent directly to keep the original color. */ successor->parent = node->parent; successor->children[RBTREE_LEFT] = node->children[RBTREE_LEFT]; rbtree_node_set_parent(successor->children[RBTREE_LEFT], successor); if (node == parent) { parent = successor; } else { successor->children[RBTREE_RIGHT] = node->children[RBTREE_RIGHT]; rbtree_node_set_parent(successor->children[RBTREE_RIGHT], successor); parent->children[RBTREE_LEFT] = child; if (child != NULL) { rbtree_node_set_parent(child, parent); } } goto update_color; } /* * Node has at most one child. */ color = rbtree_node_color(node); parent = rbtree_node_parent(node); if (child != NULL) { rbtree_node_set_parent(child, parent); } if (unlikely(parent == NULL)) { tree->root = child; } else { parent->children[rbtree_node_index(node, parent)] = child; } /* * The node has been removed, update the colors. The child pointer can * be NULL, in which case it is considered a black leaf. */ update_color: if (color == RBTREE_COLOR_RED) { return; } for (;;) { if ((child != NULL) && rbtree_node_is_red(child)) { rbtree_node_set_black(child); break; } if (parent == NULL) { break; } left = rbtree_node_index(child, parent); right = 1 - left; brother = parent->children[right]; /* * Brother is red. Recolor and rotate left at parent so that brother * becomes black. */ if (rbtree_node_is_red(brother)) { rbtree_node_set_black(brother); rbtree_node_set_red(parent); rbtree_rotate(tree, parent, left); brother = parent->children[right]; } assert(brother != NULL); /* * Brother has no red child. Recolor and repeat at parent. */ if (((brother->children[RBTREE_LEFT] == NULL) || rbtree_node_is_black(brother->children[RBTREE_LEFT])) && ((brother->children[RBTREE_RIGHT] == NULL) || rbtree_node_is_black(brother->children[RBTREE_RIGHT]))) { rbtree_node_set_red(brother); child = parent; parent = rbtree_node_parent(child); continue; } /* * Brother's right child is black. Recolor and rotate right at brother. */ if ((brother->children[right] == NULL) || rbtree_node_is_black(brother->children[right])) { rbtree_node_set_black(brother->children[left]); rbtree_node_set_red(brother); rbtree_rotate(tree, brother, right); brother = parent->children[right]; } /* * Brother's left child is black. Exchange parent and brother colors * (we already know brother is black), set brother's right child black, * rotate left at parent and leave. */ assert(brother->children[right] != NULL); rbtree_node_set_color(brother, rbtree_node_color(parent)); rbtree_node_set_black(parent); rbtree_node_set_black(brother->children[right]); rbtree_rotate(tree, parent, left); break; } assert((tree->root == NULL) || rbtree_node_is_black(tree->root)); } struct rbtree_node * rbtree_nearest(struct rbtree_node *parent, int index, int direction) { assert(rbtree_check_index(direction)); if (parent == NULL) { return NULL; } assert(rbtree_check_index(index)); if (index != direction) { return parent; } return rbtree_walk(parent, direction); } struct rbtree_node * rbtree_firstlast(const struct rbtree *tree, int direction) { struct rbtree_node *prev, *cur; assert(rbtree_check_index(direction)); prev = NULL; for (cur = tree->root; cur != NULL; cur = cur->children[direction]) { prev = cur; } return prev; } struct rbtree_node * rbtree_walk(struct rbtree_node *node, int direction) { int left, right; assert(rbtree_check_index(direction)); left = direction; right = 1 - left; if (node == NULL) { return NULL; } if (node->children[left] != NULL) { node = node->children[left]; while (node->children[right] != NULL) { node = node->children[right]; } } else { struct rbtree_node *parent; int index; for (;;) { parent = rbtree_node_parent(node); if (parent == NULL) { return NULL; } index = rbtree_node_index(node, parent); node = parent; if (index == right) { break; } } } return node; } struct rbtree_node * rbtree_postwalk_deepest(const struct rbtree *tree) { struct rbtree_node *node; node = tree->root; if (node == NULL) { return NULL; } return rbtree_node_find_deepest(node); } struct rbtree_node * rbtree_postwalk_unlink(struct rbtree_node *node) { struct rbtree_node *parent; int index; if (node == NULL) { return NULL; } assert(node->children[RBTREE_LEFT] == NULL); assert(node->children[RBTREE_RIGHT] == NULL); parent = rbtree_node_parent(node); if (parent == NULL) { return NULL; } index = rbtree_node_index(node, parent); parent->children[index] = NULL; node = parent->children[RBTREE_RIGHT]; if (node == NULL) { return parent; } return rbtree_node_find_deepest(node); }