void rb_insert_fixup(Node* &T, Node *n) { // 如果n的父亲是红色,则需要调整 // 如果n的父亲是黑色,则不需要调整,因为n本身是红色 while(IS_RED(PARENT(n))) { // 根据n的叔叔节点的颜色,来决定调整方案 Node *p = IS_LEFT(PARENT(n))? RIGHT(PARENT(PARENT(n))): LEFT(PARENT(PARENT(n))); // 如果叔叔是红色,那很简单,把爷爷的黑色转移给父亲和叔叔,爷爷刷成红色 // 这样,即满足了性质4,也没有破坏性质5及其他性质 // 但是,爷爷可能破坏了红黑性质4,则从爷爷开始继续调整(向上递归了两层) if (IS_RED(p)) { // 父亲刷成黑色 SET_BLACK(PARENT(n)); // 叔叔刷成黑色 SET_BLACK(p); // 爷爷刷成红色 SET_RED(PARENT(PARENT(n))); // 从爷爷开始继续调整 n = PARENT(PARENT(n)); continue; } // 如果叔叔是黑色,就复杂一点,引入旋转操作 // 如果n是左孩子,那么需要一次右旋+颜色调整即可 // 如果n是右孩子,则通过一次左旋调整成左孩子,然后按上面情况处理 if (IS_LEFT(PARENT(n))) { // 如果n是右孩子,通过右旋调整成左孩子 if (IS_RIGHT(n)) { n = PARENT(n); left_rotate(T, n); } // 现在n是左孩子了 SET_BLACK(PARENT(n)); SET_RED(PARENT(PARENT(n))); right_rotate(T, PARENT(PARENT(n))); } else { if (IS_LEFT(n)) { n = PARENT(n); right_rotate(T,n); } SET_BLACK(PARENT(n)); SET_RED(PARENT(PARENT(n))); left_rotate(T,PARENT(PARENT(n))); } } // 如果n是根节点,则把根设置为黑色 if (NIL == PARENT(n)) SET_BLACK(n); }
static void aoff_link_free_block(Allctr_t *allctr, Block_t *block, Uint32 flags) { AOFFAllctr_t *alc = (AOFFAllctr_t *) allctr; AOFF_RBTree_t *blk = (AOFF_RBTree_t *) block; AOFF_RBTree_t **root = ((flags & ERTS_ALCU_FLG_SBMBC) ? &alc->sbmbc_root : &alc->mbc_root); Uint blk_sz = BLK_SZ(blk); #ifdef HARD_DEBUG check_tree(*root, 0); #endif blk->flags = 0; blk->left = NULL; blk->right = NULL; blk->max_sz = blk_sz; if (!*root) { blk->parent = NULL; SET_BLACK(blk); *root = blk; } else { AOFF_RBTree_t *x = *root; while (1) { if (x->max_sz < blk_sz) { x->max_sz = blk_sz; } if (blk < x) { if (!x->left) { blk->parent = x; x->left = blk; break; } x = x->left; } else { if (!x->right) { blk->parent = x; x->right = blk; break; } x = x->right; } } /* Insert block into size tree */ RBT_ASSERT(blk->parent); SET_RED(blk); if (IS_RED(blk->parent)) tree_insert_fixup(root, blk); } #ifdef HARD_DEBUG check_tree(*root, 0); #endif }
static void aobf_link_free_block(Allctr_t *allctr, Block_t *block) { BFAllctr_t *bfallctr = (BFAllctr_t *) allctr; RBTree_t **root = &bfallctr->mbc_root; RBTree_t *blk = (RBTree_t *) block; Uint blk_sz = BF_BLK_SZ(blk); blk->flags = 0; blk->left = NULL; blk->right = NULL; if (!*root) { blk->parent = NULL; SET_BLACK(blk); *root = blk; } else { RBTree_t *x = *root; while (1) { Uint size; size = BF_BLK_SZ(x); if (blk_sz < size || (blk_sz == size && blk < x)) { if (!x->left) { blk->parent = x; x->left = blk; break; } x = x->left; } else { if (!x->right) { blk->parent = x; x->right = blk; break; } x = x->right; } } /* Insert block into size tree */ RBT_ASSERT(blk->parent); SET_RED(blk); if (IS_RED(blk->parent)) tree_insert_fixup(root, blk); } #ifdef HARD_DEBUG check_tree(root, 1, 0); #endif }
Node *malloc_node(Interval key) { Node *n = (Node *)malloc(sizeof(Node)); assert(n); KEY(n) = key; SET_RED(n); PARENT(n) = LEFT(n) = RIGHT(n) = &NIL_NODE; n->max = HIGH(key); return n; }
Node *malloc_node(int key) { Node *n = (Node *)malloc(sizeof(Node)); assert(n); KEY(n) = key; SET_RED(n); SIZE(n) = 1; PARENT(n) = LEFT(n) = RIGHT(n) = &NIL_NODE; return n; }
Node* tree_insert(Node* &T, Interval key) { // 分配新节点 Node *n = malloc_node(key); // 如果当前是空树,则n节点作为根,刷成黑色即满足红黑性质 if (NIL == T){ SET_BLACK(n); T = n; return n; } // 如果当前不是空树,则先找到插入位置 Node *p = T; Node *q; while(NIL != p) { // 调整路径上节点的max值 if (MAX(p) < HIGH(key)) MAX(p) = HIGH(key); q = p; if (LT(key,KEY(p))) p = LEFT(p); else p = RIGHT(p); } // 找到了插入位置,n节点的父亲为q PARENT(n) = q; if (LT(key, KEY(q))) { LEFT(q) = n; } else { RIGHT(q) = n; } // 设置n节点为红色 // 这样只可能违背红黑性质4(性质4的调整应该比性质5简单) SET_RED(n); // 从n节点开始调整,使之符合红黑性质4 // 调整的每一步,都不会破坏其他红黑性质 rb_insert_fixup(T, n); return n; }
Node* tree_insert(Node* &T, int key) { // 分配新节点 Node *n = malloc_node(key); // 如果当前是空树,则n节点作为根,刷成黑色即满足红黑性质 if (NIL == T){ SET_BLACK(n); T = n; return n; } // 如果当前不是空树,则先找到插入位置 Node *p = T; Node *q; while(NIL != p) { // 每经过一个节点,其size加一 SIZE(p)++; q = p; if (key < KEY(p)) p = LEFT(p); else p = RIGHT(p); } // 找到了插入位置,n节点的父亲为q PARENT(n) = q; if (key < KEY(q)) { LEFT(q) = n; } else { RIGHT(q) = n; } // 设置n节点为红色 // 这样只可能违背红黑性质4(性质4的调整应该比性质5简单) SET_RED(n); // 从n节点开始调整,使之符合红黑性质4 // 调整的每一步,都不会破坏其他红黑性质 rb_insert_fixup(T, n); return n; }
static void bf_link_free_block(Allctr_t *allctr, Block_t *block) { BFAllctr_t *bfallctr = (BFAllctr_t *) allctr; RBTree_t **root = &bfallctr->mbc_root; RBTree_t *blk = (RBTree_t *) block; Uint blk_sz = BF_BLK_SZ(blk); SET_TREE_NODE(blk); blk->flags = 0; blk->left = NULL; blk->right = NULL; if (!*root) { blk->parent = NULL; SET_BLACK(blk); *root = blk; } else { RBTree_t *x = *root; while (1) { Uint size; size = BF_BLK_SZ(x); if (blk_sz == size) { SET_LIST_ELEM(blk); LIST_NEXT(blk) = LIST_NEXT(x); LIST_PREV(blk) = x; if (LIST_NEXT(x)) LIST_PREV(LIST_NEXT(x)) = blk; LIST_NEXT(x) = blk; return; /* Finnished */ } else if (blk_sz < size) { if (!x->left) { blk->parent = x; x->left = blk; break; } x = x->left; } else { if (!x->right) { blk->parent = x; x->right = blk; break; } x = x->right; } } RBT_ASSERT(blk->parent); SET_RED(blk); if (IS_RED(blk->parent)) tree_insert_fixup(root, blk); } SET_TREE_NODE(blk); LIST_NEXT(blk) = NULL; #ifdef HARD_DEBUG check_tree(root, 0, 0); #endif }
/* * The argument types of "Allctr_t *" and "Block_t *" have been * chosen since we then can use tree_delete() as unlink_free_block * callback function in the address order case. */ static void tree_delete(Allctr_t *allctr, Block_t *del) { BFAllctr_t *bfallctr = (BFAllctr_t *) allctr; Uint spliced_is_black; RBTree_t **root = &bfallctr->mbc_root; RBTree_t *x, *y, *z = (RBTree_t *) del; RBTree_t null_x; /* null_x is used to get the fixup started when we splice out a node without children. */ null_x.parent = NULL; #ifdef HARD_DEBUG check_tree(*root, bfallctr->address_order, 0); #endif /* Remove node from tree... */ /* Find node to splice out */ if (!z->left || !z->right) y = z; else /* Set y to z:s successor */ for(y = z->right; y->left; y = y->left); /* splice out y */ x = y->left ? y->left : y->right; spliced_is_black = IS_BLACK(y); if (x) { x->parent = y->parent; } else if (!x && spliced_is_black) { x = &null_x; x->flags = 0; SET_BLACK(x); x->right = x->left = NULL; x->parent = y->parent; y->left = x; } if (!y->parent) { RBT_ASSERT(*root == y); *root = x; } else if (y == y->parent->left) y->parent->left = x; else { RBT_ASSERT(y == y->parent->right); y->parent->right = x; } if (y != z) { /* We spliced out the successor of z; replace z by the successor */ replace(root, z, y); } if (spliced_is_black) { /* We removed a black node which makes the resulting tree violate the Red-Black Tree properties. Fixup tree... */ while (IS_BLACK(x) && x->parent) { /* * x has an "extra black" which we move up the tree * until we reach the root or until we can get rid of it. * * y is the sibbling of x */ if (x == x->parent->left) { y = x->parent->right; RBT_ASSERT(y); if (IS_RED(y)) { RBT_ASSERT(y->right); RBT_ASSERT(y->left); SET_BLACK(y); RBT_ASSERT(IS_BLACK(x->parent)); SET_RED(x->parent); left_rotate(root, x->parent); y = x->parent->right; } RBT_ASSERT(y); RBT_ASSERT(IS_BLACK(y)); if (IS_BLACK(y->left) && IS_BLACK(y->right)) { SET_RED(y); x = x->parent; } else { if (IS_BLACK(y->right)) { SET_BLACK(y->left); SET_RED(y); right_rotate(root, y); y = x->parent->right; } RBT_ASSERT(y); if (IS_RED(x->parent)) { SET_BLACK(x->parent); SET_RED(y); } RBT_ASSERT(y->right); SET_BLACK(y->right); left_rotate(root, x->parent); x = *root; break; } } else { RBT_ASSERT(x == x->parent->right); y = x->parent->left; RBT_ASSERT(y); if (IS_RED(y)) { RBT_ASSERT(y->right); RBT_ASSERT(y->left); SET_BLACK(y); RBT_ASSERT(IS_BLACK(x->parent)); SET_RED(x->parent); right_rotate(root, x->parent); y = x->parent->left; } RBT_ASSERT(y); RBT_ASSERT(IS_BLACK(y)); if (IS_BLACK(y->right) && IS_BLACK(y->left)) { SET_RED(y); x = x->parent; } else { if (IS_BLACK(y->left)) { SET_BLACK(y->right); SET_RED(y); left_rotate(root, y); y = x->parent->left; } RBT_ASSERT(y); if (IS_RED(x->parent)) { SET_BLACK(x->parent); SET_RED(y); } RBT_ASSERT(y->left); SET_BLACK(y->left); right_rotate(root, x->parent); x = *root; break; } } } SET_BLACK(x); if (null_x.parent) { if (null_x.parent->left == &null_x) null_x.parent->left = NULL; else { RBT_ASSERT(null_x.parent->right == &null_x); null_x.parent->right = NULL; } RBT_ASSERT(!null_x.left); RBT_ASSERT(!null_x.right); } else if (*root == &null_x) { *root = NULL; RBT_ASSERT(!null_x.left); RBT_ASSERT(!null_x.right); } } DESTROY_TREE_NODE(del); #ifdef HARD_DEBUG check_tree(root, bfallctr->address_order, 0); #endif }
static void tree_insert_fixup(RBTree_t **root, RBTree_t *blk) { RBTree_t *x = blk, *y; /* * Rearrange the tree so that it satisfies the Red-Black Tree properties */ RBT_ASSERT(x != *root && IS_RED(x->parent)); do { /* * x and its parent are both red. Move the red pair up the tree * until we get to the root or until we can separate them. */ RBT_ASSERT(IS_RED(x)); RBT_ASSERT(IS_BLACK(x->parent->parent)); RBT_ASSERT(x->parent->parent); if (x->parent == x->parent->parent->left) { y = x->parent->parent->right; if (IS_RED(y)) { SET_BLACK(y); x = x->parent; SET_BLACK(x); x = x->parent; SET_RED(x); } else { if (x == x->parent->right) { x = x->parent; left_rotate(root, x); } RBT_ASSERT(x == x->parent->parent->left->left); RBT_ASSERT(IS_RED(x)); RBT_ASSERT(IS_RED(x->parent)); RBT_ASSERT(IS_BLACK(x->parent->parent)); RBT_ASSERT(IS_BLACK(y)); SET_BLACK(x->parent); SET_RED(x->parent->parent); right_rotate(root, x->parent->parent); RBT_ASSERT(x == x->parent->left); RBT_ASSERT(IS_RED(x)); RBT_ASSERT(IS_RED(x->parent->right)); RBT_ASSERT(IS_BLACK(x->parent)); break; } } else { RBT_ASSERT(x->parent == x->parent->parent->right); y = x->parent->parent->left; if (IS_RED(y)) { SET_BLACK(y); x = x->parent; SET_BLACK(x); x = x->parent; SET_RED(x); } else { if (x == x->parent->left) { x = x->parent; right_rotate(root, x); } RBT_ASSERT(x == x->parent->parent->right->right); RBT_ASSERT(IS_RED(x)); RBT_ASSERT(IS_RED(x->parent)); RBT_ASSERT(IS_BLACK(x->parent->parent)); RBT_ASSERT(IS_BLACK(y)); SET_BLACK(x->parent); SET_RED(x->parent->parent); left_rotate(root, x->parent->parent); RBT_ASSERT(x == x->parent->right); RBT_ASSERT(IS_RED(x)); RBT_ASSERT(IS_RED(x->parent->left)); RBT_ASSERT(IS_BLACK(x->parent)); break; } } } while (x != *root && IS_RED(x->parent)); SET_BLACK(*root); }
static void rbt_insert(enum AOFFSortOrder order, AOFF_RBTree_t** root, AOFF_RBTree_t* blk) { Uint blk_sz = AOFF_BLK_SZ(blk); #ifdef DEBUG blk->flags = (order == FF_BF) ? IS_BF_FLG : 0; #else blk->flags = 0; #endif blk->left = NULL; blk->right = NULL; blk->max_sz = blk_sz; if (!*root) { blk->parent = NULL; SET_BLACK(blk); *root = blk; } else { AOFF_RBTree_t *x = *root; while (1) { SWord diff; if (x->max_sz < blk_sz) { x->max_sz = blk_sz; } diff = cmp_blocks(order, blk, x); if (diff < 0) { if (!x->left) { blk->parent = x; x->left = blk; break; } x = x->left; } else if (diff > 0) { if (!x->right) { blk->parent = x; x->right = blk; break; } x = x->right; } else { ASSERT(order == FF_BF); ASSERT(blk->flags & IS_BF_FLG); ASSERT(x->flags & IS_BF_FLG); SET_LIST_ELEM(blk); LIST_NEXT(blk) = LIST_NEXT(x); LIST_PREV(blk) = x; if (LIST_NEXT(x)) LIST_PREV(LIST_NEXT(x)) = blk; LIST_NEXT(x) = blk; return; } } /* Insert block into size tree */ RBT_ASSERT(blk->parent); SET_RED(blk); if (IS_RED(blk->parent)) tree_insert_fixup(root, blk); } if (order == FF_BF) { SET_TREE_NODE(blk); LIST_NEXT(blk) = NULL; } }
static void rbt_delete(AOFF_RBTree_t** root, AOFF_RBTree_t* del) { Uint spliced_is_black; AOFF_RBTree_t *x, *y, *z = del; AOFF_RBTree_t null_x; /* null_x is used to get the fixup started when we splice out a node without children. */ HARD_CHECK_IS_MEMBER(*root, del); null_x.parent = NULL; /* Remove node from tree... */ /* Find node to splice out */ if (!z->left || !z->right) y = z; else /* Set y to z:s successor */ for(y = z->right; y->left; y = y->left); /* splice out y */ x = y->left ? y->left : y->right; spliced_is_black = IS_BLACK(y); if (x) { x->parent = y->parent; } else if (spliced_is_black) { x = &null_x; x->flags = 0; SET_BLACK(x); x->right = x->left = NULL; x->max_sz = 0; x->parent = y->parent; y->left = x; } if (!y->parent) { RBT_ASSERT(*root == y); *root = x; } else { if (y == y->parent->left) { y->parent->left = x; } else { RBT_ASSERT(y == y->parent->right); y->parent->right = x; } if (y->parent != z) { lower_max_size(y->parent, (y==z ? NULL : z)); } } if (y != z) { /* We spliced out the successor of z; replace z by the successor */ ASSERT(z != &null_x); replace(root, z, y); lower_max_size(y, NULL); } if (spliced_is_black) { /* We removed a black node which makes the resulting tree violate the Red-Black Tree properties. Fixup tree... */ while (IS_BLACK(x) && x->parent) { /* * x has an "extra black" which we move up the tree * until we reach the root or until we can get rid of it. * * y is the sibbling of x */ if (x == x->parent->left) { y = x->parent->right; RBT_ASSERT(y); if (IS_RED(y)) { RBT_ASSERT(y->right); RBT_ASSERT(y->left); SET_BLACK(y); RBT_ASSERT(IS_BLACK(x->parent)); SET_RED(x->parent); left_rotate(root, x->parent); y = x->parent->right; } RBT_ASSERT(y); RBT_ASSERT(IS_BLACK(y)); if (IS_BLACK(y->left) && IS_BLACK(y->right)) { SET_RED(y); x = x->parent; } else { if (IS_BLACK(y->right)) { SET_BLACK(y->left); SET_RED(y); right_rotate(root, y); y = x->parent->right; } RBT_ASSERT(y); if (IS_RED(x->parent)) { SET_BLACK(x->parent); SET_RED(y); } RBT_ASSERT(y->right); SET_BLACK(y->right); left_rotate(root, x->parent); x = *root; break; } } else { RBT_ASSERT(x == x->parent->right); y = x->parent->left; RBT_ASSERT(y); if (IS_RED(y)) { RBT_ASSERT(y->right); RBT_ASSERT(y->left); SET_BLACK(y); RBT_ASSERT(IS_BLACK(x->parent)); SET_RED(x->parent); right_rotate(root, x->parent); y = x->parent->left; } RBT_ASSERT(y); RBT_ASSERT(IS_BLACK(y)); if (IS_BLACK(y->right) && IS_BLACK(y->left)) { SET_RED(y); x = x->parent; } else { if (IS_BLACK(y->left)) { SET_BLACK(y->right); SET_RED(y); left_rotate(root, y); y = x->parent->left; } RBT_ASSERT(y); if (IS_RED(x->parent)) { SET_BLACK(x->parent); SET_RED(y); } RBT_ASSERT(y->left); SET_BLACK(y->left); right_rotate(root, x->parent); x = *root; break; } } } SET_BLACK(x); if (null_x.parent) { if (null_x.parent->left == &null_x) null_x.parent->left = NULL; else { RBT_ASSERT(null_x.parent->right == &null_x); null_x.parent->right = NULL; } RBT_ASSERT(!null_x.left); RBT_ASSERT(!null_x.right); } else if (*root == &null_x) { *root = NULL; RBT_ASSERT(!null_x.left); RBT_ASSERT(!null_x.right); } } }
void rb_delete_fixup(Node* &T, Node *x) { while ((NIL!= x) && !IS_ROOT(x) && IS_BLACK(x)) { if (IS_LEFT(x)) { // w是x的右兄弟,w是下面不同处理方式的选择依据 // 总共四种处理方式: // case 1: w是红色,两个孩子的颜色无所谓 // case 2: w是黑色,左孩子黑色,右孩子黑色 // case 3: w是黑色,左孩子红色,右孩子黑色 // case 4: w是黑色,右孩子红色,左孩子的颜色无所谓 Node *w = RIGHT(PARENT(x)); // case1: w是红色,则通过一次左旋,并刷成黑色,转成case 2、3、4 if (IS_RED(w)) { SET_BLACK(w); SET_RED(PARENT(x)); left_rotate(T, PARENT(x)); } // case 2: w的两个孩子都是黑色,把w刷成红色,x的父亲取代x,向上递归处理 if (IS_BLACK(LEFT(w)) && IS_BLACK(RIGHT(w))) { SET_RED(w); x = PARENT(x); continue; } // case 3: w的左孩子红色,右孩子黑色,把w左孩子刷成黑色,w刷成红色,做一次右旋,转成case 4 if (IS_BLACK(RIGHT(w))) { SET_BLACK(LEFT(w)); SET_RED(w); right_rotate(T, w); w = PARENT(w); // 转成case 4 } // case 4: w的右孩子为红色,把w刷成红色,w右节点刷成黑色,x父亲刷成黑色,做一次左旋,满足红黑性质,结束处理 COLOR(w) = COLOR(PARENT(x)); SET_BLACK(RIGHT(w)); SET_BLACK(PARENT(x)); left_rotate(T, PARENT(x)); x = T; } else { // w是x的左兄弟,w是下面不同处理方式的选择依据 // 总共四种处理方式: // case 1: w是红色,两个孩子的颜色无所谓 // case 2: w是黑色,左孩子黑色,右孩子黑色 // case 3: w是黑色,左孩子红色,右孩子黑色 // case 4: w是黑色,右孩子红色,左孩子的颜色无所谓 Node *w = LEFT(PARENT(x)); // case1: w是红色,则通过一次右旋,并刷成黑色,转成case 2、3、4 if (IS_RED(w)) { SET_BLACK(w); SET_RED(PARENT(x)); right_rotate(T, PARENT(x)); } // case 2: w的两个孩子都是黑色,把w刷成红色,x的父亲取代x,线上递归处理 if (IS_BLACK(LEFT(w)) && IS_BLACK(RIGHT(w))) { SET_RED(w); x = PARENT(x); continue; } // case 3: w的左孩子黑色,右孩子红色,把w右孩子刷成黑色,w刷成红色,做一次左旋,转成case 4 if (IS_BLACK(LEFT(w))) { SET_BLACK(RIGHT(w)); SET_RED(w); left_rotate(T, w); w = PARENT(w); // 转成case 4 } // case 4: w的左孩子为红色,把w刷成红色,w左节点刷成黑色,x父亲刷成黑色,做一次右旋,满足红黑性质,结束处理 COLOR(w) = COLOR(PARENT(x)); SET_BLACK(LEFT(w)); SET_BLACK(PARENT(x)); right_rotate(T, PARENT(x)); x = T; } } // 如果x是根节点,或为红色,则都刷成黑色,即可保持红黑树性质 SET_BLACK(x); }