Valid 3 code version
This commit is contained in:
@@ -1,387 +1,454 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "rbtree.h"
|
||||
#include "log.h"
|
||||
#include "object_allocator.h"
|
||||
|
||||
struct RbtFactory {
|
||||
TraceTag tag;
|
||||
struct slab_allocator queue_ele_allocator;
|
||||
struct slab_allocator rbtnode_ele_allocator;
|
||||
};
|
||||
|
||||
struct Queue {
|
||||
struct RbtNode* key;
|
||||
struct Queue* next;
|
||||
};
|
||||
|
||||
static struct RbtFactory rbt_factory;
|
||||
|
||||
void module_rbt_factory_init(TraceTag* _softkernel_tag)
|
||||
{
|
||||
CreateResourceTag(&rbt_factory.tag, _softkernel_tag, "GlobalRbtFactory", TRACER_SYSOBJECT, &rbt_factory);
|
||||
slab_init(&rbt_factory.queue_ele_allocator, sizeof(struct Queue));
|
||||
slab_init(&rbt_factory.rbtnode_ele_allocator, sizeof(struct RbtNode));
|
||||
}
|
||||
|
||||
struct Queue* front = NULL;
|
||||
struct Queue* rear = NULL;
|
||||
void delete_case1(RbtTree* tree, RbtNode* node);
|
||||
void delete_case2(RbtTree* tree, RbtNode* node);
|
||||
void delete_case3(RbtTree* tree, RbtNode* node);
|
||||
void delete_case4(RbtTree* tree, RbtNode* node);
|
||||
void delete_case5(RbtTree* tree, RbtNode* node);
|
||||
void delete_case6(RbtTree* tree, RbtNode* node);
|
||||
|
||||
struct RbtNode* pfront()
|
||||
static inline enum rbt_type get_color(RbtNode* node)
|
||||
{
|
||||
struct RbtNode* key;
|
||||
key = front->key;
|
||||
return key;
|
||||
}
|
||||
|
||||
int isempty()
|
||||
{
|
||||
if (front == NULL)
|
||||
return 1;
|
||||
|
||||
if (node == NULL)
|
||||
return BLACK;
|
||||
else
|
||||
return 0;
|
||||
return node->color;
|
||||
}
|
||||
|
||||
void dequeue()
|
||||
static inline void set_color(enum rbt_type color, RbtNode* node)
|
||||
{
|
||||
if (isempty())
|
||||
return;
|
||||
|
||||
struct Queue* temp = front;
|
||||
front = front->next;
|
||||
slab_free(&rbt_factory.queue_ele_allocator, (void*)temp);
|
||||
assert(node != NULL);
|
||||
node->color = color;
|
||||
}
|
||||
|
||||
void enqueue(struct RbtNode* key)
|
||||
static inline RbtNode* get_parent(RbtNode* node)
|
||||
{
|
||||
struct Queue* temp = (struct Queue*)slab_alloc(&rbt_factory.queue_ele_allocator);
|
||||
temp->key = key;
|
||||
temp->next = NULL;
|
||||
|
||||
if (front == NULL && rear == NULL) {
|
||||
front = rear = temp;
|
||||
return;
|
||||
}
|
||||
|
||||
rear->next = temp;
|
||||
rear = temp;
|
||||
assert(node != NULL);
|
||||
return node->parent;
|
||||
}
|
||||
|
||||
void levelorder(struct RbtNode* root)
|
||||
static inline void set_parent(RbtNode* parent, RbtNode* node)
|
||||
{
|
||||
if (root == NULL)
|
||||
return;
|
||||
|
||||
enqueue(root);
|
||||
|
||||
while (!isempty()) {
|
||||
struct RbtNode* current = pfront();
|
||||
DEBUG("%d ", current->key);
|
||||
|
||||
if (current->left != NULL)
|
||||
enqueue(current->left);
|
||||
|
||||
if (current->right != NULL)
|
||||
enqueue(current->right);
|
||||
|
||||
dequeue();
|
||||
}
|
||||
assert(node != NULL);
|
||||
node->parent = parent;
|
||||
}
|
||||
|
||||
void LeftRotate(struct RbtNode** T, struct RbtNode** x)
|
||||
static int is_root(RbtNode* node)
|
||||
{
|
||||
struct RbtNode* y = (*x)->right;
|
||||
(*x)->right = y->left;
|
||||
assert(node != NULL);
|
||||
return (get_parent(node) == NULL);
|
||||
}
|
||||
|
||||
if (y->left != NULL)
|
||||
y->left->parent = *x;
|
||||
static inline int is_black(RbtNode* node)
|
||||
{
|
||||
assert(node != NULL);
|
||||
return (get_color(node) == BLACK);
|
||||
}
|
||||
|
||||
y->parent = (*x)->parent;
|
||||
|
||||
if ((*x)->parent == NULL)
|
||||
*T = y;
|
||||
|
||||
else if (*x == (*x)->parent->left)
|
||||
(*x)->parent->left = y;
|
||||
static inline int is_red(RbtNode* node)
|
||||
{
|
||||
assert(node != NULL);
|
||||
return (get_color(node) == RED);
|
||||
}
|
||||
|
||||
RbtNode* sibling(RbtNode* node)
|
||||
{
|
||||
assert(node != NULL);
|
||||
assert(node->parent != NULL); /* Root node has no sibling */
|
||||
if (node == node->parent->left)
|
||||
return node->parent->right;
|
||||
else
|
||||
(*x)->parent->right = y;
|
||||
|
||||
y->left = *x;
|
||||
|
||||
(*x)->parent = y;
|
||||
return node->parent->left;
|
||||
}
|
||||
void RightRotate(struct RbtNode** T, struct RbtNode** x)
|
||||
static inline RbtNode* get_min(RbtNode* node)
|
||||
{
|
||||
struct RbtNode* y = (*x)->left;
|
||||
(*x)->left = y->right;
|
||||
|
||||
if (y->right != NULL)
|
||||
y->right->parent = *x;
|
||||
|
||||
y->parent = (*x)->parent;
|
||||
|
||||
if ((*x)->parent == NULL)
|
||||
*T = y;
|
||||
|
||||
else if ((*x) == (*x)->parent->left)
|
||||
(*x)->parent->left = y;
|
||||
|
||||
else
|
||||
(*x)->parent->right = y;
|
||||
|
||||
y->right = *x;
|
||||
(*x)->parent = y;
|
||||
}
|
||||
|
||||
void RB_insert_fixup(struct RbtNode** T, struct RbtNode** z)
|
||||
{
|
||||
struct RbtNode* grandparent = NULL;
|
||||
struct RbtNode* parentpt = NULL;
|
||||
|
||||
while (((*z) != *T) && ((*z)->color != BLACK) && ((*z)->parent->color == RED)) {
|
||||
parentpt = (*z)->parent;
|
||||
grandparent = (*z)->parent->parent;
|
||||
|
||||
if (parentpt == grandparent->left) {
|
||||
struct RbtNode* uncle = grandparent->right;
|
||||
|
||||
if (uncle != NULL && uncle->color == RED) {
|
||||
grandparent->color = RED;
|
||||
parentpt->color = BLACK;
|
||||
uncle->color = BLACK;
|
||||
*z = grandparent;
|
||||
}
|
||||
|
||||
else {
|
||||
if ((*z) == parentpt->right) {
|
||||
LeftRotate(T, &parentpt);
|
||||
(*z) = parentpt;
|
||||
parentpt = (*z)->parent;
|
||||
}
|
||||
|
||||
RightRotate(T, &grandparent);
|
||||
parentpt->color = BLACK;
|
||||
grandparent->color = RED;
|
||||
(*z) = parentpt;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
struct RbtNode* uncle = grandparent->left;
|
||||
|
||||
if (uncle != NULL && uncle->color == RED) {
|
||||
grandparent->color = RED;
|
||||
parentpt->color = BLACK;
|
||||
uncle->color = BLACK;
|
||||
(*z) = grandparent;
|
||||
}
|
||||
|
||||
else {
|
||||
if ((*z) == parentpt->left) {
|
||||
RightRotate(T, &parentpt);
|
||||
(*z) = parentpt;
|
||||
parentpt = (*z)->parent;
|
||||
}
|
||||
|
||||
LeftRotate(T, &grandparent);
|
||||
parentpt->color = BLACK;
|
||||
grandparent->color = RED;
|
||||
(*z) = parentpt;
|
||||
}
|
||||
}
|
||||
assert(node != NULL);
|
||||
while (node->left) {
|
||||
node = node->left;
|
||||
}
|
||||
(*T)->color = BLACK;
|
||||
return node;
|
||||
}
|
||||
|
||||
struct RbtNode* rbt_insert(struct RbtNode* T, uintptr_t key, void* data)
|
||||
static inline RbtNode* get_max(RbtNode* node)
|
||||
{
|
||||
struct RbtNode* z = (struct RbtNode*)slab_alloc(&rbt_factory.rbtnode_ele_allocator);
|
||||
z->key = key;
|
||||
z->data = data;
|
||||
z->left = NULL;
|
||||
z->right = NULL;
|
||||
z->parent = NULL;
|
||||
z->color = RED;
|
||||
|
||||
struct RbtNode* y = NULL;
|
||||
struct RbtNode* x = T; // root
|
||||
|
||||
while (x != NULL) {
|
||||
y = x;
|
||||
if (z->key < x->key)
|
||||
x = x->left;
|
||||
|
||||
else
|
||||
x = x->right;
|
||||
assert(node != NULL);
|
||||
while (node->right) {
|
||||
node = node->right;
|
||||
}
|
||||
z->parent = y;
|
||||
|
||||
if (y == NULL)
|
||||
T = z;
|
||||
|
||||
else if (z->key < y->key)
|
||||
y->left = z;
|
||||
|
||||
else
|
||||
y->right = z;
|
||||
|
||||
RB_insert_fixup(&T, &z);
|
||||
|
||||
return T;
|
||||
return node;
|
||||
}
|
||||
|
||||
void preorder(struct RbtNode* root)
|
||||
RbtNode* rbtree_min(RbtTree* tree)
|
||||
{
|
||||
if (root == NULL)
|
||||
return;
|
||||
|
||||
DEBUG("%d ", root->key);
|
||||
preorder(root->left);
|
||||
preorder(root->right);
|
||||
}
|
||||
|
||||
struct RbtNode* Tree_minimum(struct RbtNode* RbtNode)
|
||||
{
|
||||
while (RbtNode->left != NULL)
|
||||
RbtNode = RbtNode->left;
|
||||
|
||||
return RbtNode;
|
||||
}
|
||||
|
||||
void RB_delete_fixup(struct RbtNode** T, struct RbtNode** x)
|
||||
{
|
||||
while ((*x) != *T && (*x)->color == BLACK) {
|
||||
if ((*x) == (*x)->parent->left) {
|
||||
struct RbtNode* w = (*x)->parent->right;
|
||||
|
||||
if (w->color == RED) {
|
||||
w->color = BLACK;
|
||||
(*x)->parent->color = BLACK;
|
||||
LeftRotate(T, &((*x)->parent));
|
||||
w = (*x)->parent->right;
|
||||
}
|
||||
|
||||
if (w->left->color == BLACK && w->right->color == BLACK) {
|
||||
w->color = RED;
|
||||
(*x) = (*x)->parent;
|
||||
}
|
||||
|
||||
else {
|
||||
if (w->right->color == BLACK) {
|
||||
w->left->color = BLACK;
|
||||
w->color = RED;
|
||||
RightRotate(T, &w);
|
||||
w = (*x)->parent->right;
|
||||
}
|
||||
|
||||
w->color = (*x)->parent->color;
|
||||
(*x)->parent->color = BLACK;
|
||||
w->right->color = BLACK;
|
||||
LeftRotate(T, &((*x)->parent));
|
||||
(*x) = *T;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
struct RbtNode* w = (*x)->parent->left;
|
||||
|
||||
if (w->color == RED) {
|
||||
w->color = BLACK;
|
||||
(*x)->parent->color = BLACK;
|
||||
RightRotate(T, &((*x)->parent));
|
||||
w = (*x)->parent->left;
|
||||
}
|
||||
|
||||
if (w->right->color == BLACK && w->left->color == BLACK) {
|
||||
w->color = RED;
|
||||
(*x) = (*x)->parent;
|
||||
}
|
||||
|
||||
else {
|
||||
if (w->left->color == BLACK) {
|
||||
w->right->color = BLACK;
|
||||
w->color = RED;
|
||||
LeftRotate(T, &w);
|
||||
w = (*x)->parent->left;
|
||||
}
|
||||
|
||||
w->color = (*x)->parent->color;
|
||||
(*x)->parent->color = BLACK;
|
||||
w->left->color = BLACK;
|
||||
RightRotate(T, &((*x)->parent));
|
||||
(*x) = *T;
|
||||
}
|
||||
}
|
||||
}
|
||||
(*x)->color = BLACK;
|
||||
}
|
||||
|
||||
void RB_transplat(struct RbtNode** T, struct RbtNode** u, struct RbtNode** v)
|
||||
{
|
||||
if ((*u)->parent == NULL)
|
||||
*T = *v;
|
||||
|
||||
else if ((*u) == (*u)->parent->left)
|
||||
(*u)->parent->left = *v;
|
||||
else
|
||||
(*u)->parent->right = *v;
|
||||
|
||||
if ((*v) != NULL)
|
||||
(*v)->parent = (*u)->parent;
|
||||
}
|
||||
|
||||
struct RbtNode* rbt_delete(struct RbtNode* T, struct RbtNode* z)
|
||||
{
|
||||
struct RbtNode* y = z;
|
||||
enum rbt_type yoc;
|
||||
yoc = z->color; // y's original color
|
||||
|
||||
struct RbtNode* x;
|
||||
|
||||
if (z->left == NULL) {
|
||||
x = z->right;
|
||||
RB_transplat(&T, &z, &(z->right));
|
||||
}
|
||||
|
||||
else if (z->right == NULL) {
|
||||
x = z->left;
|
||||
RB_transplat(&T, &z, &(z->left));
|
||||
}
|
||||
|
||||
if (tree->root == NULL)
|
||||
return NULL;
|
||||
else {
|
||||
y = Tree_minimum(z->right);
|
||||
yoc = y->color;
|
||||
x = y->right;
|
||||
|
||||
if (y->parent == z)
|
||||
x->parent = y;
|
||||
|
||||
else {
|
||||
RB_transplat(&T, &y, &(y->right));
|
||||
y->right = z->right;
|
||||
y->right->parent = y;
|
||||
}
|
||||
|
||||
RB_transplat(&T, &z, &y);
|
||||
y->left = z->left;
|
||||
y->left->parent = y;
|
||||
y->color = z->color;
|
||||
return get_min(tree->root);
|
||||
}
|
||||
|
||||
if (yoc == BLACK)
|
||||
RB_delete_fixup(&T, &x);
|
||||
|
||||
slab_free(&rbt_factory.rbtnode_ele_allocator, (void*)z);
|
||||
return T;
|
||||
}
|
||||
|
||||
struct RbtNode* rbt_search(struct RbtNode* root, int x)
|
||||
RbtNode* rbtree_max(RbtTree* tree)
|
||||
{
|
||||
if (root == NULL || root->key == x)
|
||||
return root;
|
||||
if (tree->root == NULL)
|
||||
return NULL;
|
||||
else {
|
||||
return get_max(tree->root);
|
||||
}
|
||||
}
|
||||
|
||||
if (root->key > x)
|
||||
return rbt_search(root->left, x);
|
||||
RbtNode* rbtree_prev(RbtNode* node)
|
||||
{
|
||||
assert(node != NULL);
|
||||
if (node->left) {
|
||||
return get_max(node->left);
|
||||
} else {
|
||||
RbtNode* parent;
|
||||
while ((parent = get_parent(node)) && parent->left == node) {
|
||||
node = parent;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
|
||||
RbtNode* rbtree_next(RbtNode* node)
|
||||
{
|
||||
assert(node != NULL);
|
||||
|
||||
if (node->right)
|
||||
return get_min(node->right);
|
||||
else {
|
||||
RbtNode* parent = NULL;
|
||||
while ((parent = get_parent(node)) != NULL && parent->right == node) {
|
||||
node = parent;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
|
||||
RbtNode* rbtree_createnode(uintptr_t key, void* data)
|
||||
{
|
||||
RbtNode* newnode = slab_alloc(&rbt_factory.rbtnode_ele_allocator);
|
||||
if (newnode == NULL)
|
||||
return NULL;
|
||||
|
||||
newnode->key = key;
|
||||
newnode->data = data;
|
||||
newnode->parent = NULL;
|
||||
newnode->left = NULL;
|
||||
newnode->right = NULL;
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static inline int compare(uintptr_t key_a, uintptr_t key_b)
|
||||
{
|
||||
if (key_a > key_b)
|
||||
return 1;
|
||||
else if (key_a == key_b)
|
||||
return 0;
|
||||
else
|
||||
return rbt_search(root->right, x);
|
||||
return -1;
|
||||
}
|
||||
|
||||
RbtNode* do_lookup(uintptr_t key,
|
||||
RbtTree* tree,
|
||||
RbtNode** pparent)
|
||||
{
|
||||
RbtNode* current = tree->root;
|
||||
|
||||
while (current) {
|
||||
int ret = compare(current->key, key);
|
||||
if (ret == 0)
|
||||
return current;
|
||||
else {
|
||||
if (pparent != NULL) {
|
||||
*pparent = current;
|
||||
}
|
||||
if (ret < 0)
|
||||
current = current->right;
|
||||
else
|
||||
current = current->left;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RbtNode* rbt_search(RbtTree* tree, uintptr_t key)
|
||||
{
|
||||
RbtNode* node;
|
||||
node = do_lookup(key, tree, NULL);
|
||||
return node;
|
||||
}
|
||||
|
||||
static void set_child(RbtTree* tree, RbtNode* node, RbtNode* child)
|
||||
{
|
||||
int ret = compare(node->key, child->key);
|
||||
assert(ret != 0);
|
||||
|
||||
if (ret > 0) {
|
||||
node->left = child;
|
||||
} else {
|
||||
node->right = child;
|
||||
}
|
||||
}
|
||||
|
||||
static void rotate_left(RbtNode* node, RbtTree* tree)
|
||||
{
|
||||
RbtNode* p = node;
|
||||
RbtNode* q = node->right;
|
||||
RbtNode* parent = node->parent;
|
||||
if (parent == NULL) {
|
||||
tree->root = q;
|
||||
} else {
|
||||
if (parent->left == p)
|
||||
parent->left = q;
|
||||
else
|
||||
parent->right = q;
|
||||
}
|
||||
set_parent(parent, q);
|
||||
set_parent(q, p);
|
||||
|
||||
p->right = q->left;
|
||||
if (q->left)
|
||||
set_parent(p, q->left);
|
||||
q->left = p;
|
||||
}
|
||||
|
||||
static void rotate_right(RbtNode* node, RbtTree* tree)
|
||||
{
|
||||
RbtNode* p = node;
|
||||
RbtNode* q = node->left; /* can't be NULL */
|
||||
RbtNode* parent = get_parent(p);
|
||||
|
||||
if (!is_root(p)) {
|
||||
if (parent->left == p)
|
||||
parent->left = q;
|
||||
else
|
||||
parent->right = q;
|
||||
} else
|
||||
tree->root = q;
|
||||
set_parent(parent, q);
|
||||
set_parent(q, p);
|
||||
|
||||
p->left = q->right;
|
||||
if (p->left)
|
||||
set_parent(p, p->left);
|
||||
q->right = p;
|
||||
}
|
||||
|
||||
void rbtree_init(RbtTree* tree)
|
||||
{
|
||||
tree->root = NULL;
|
||||
}
|
||||
|
||||
RbtNode* __rbtree_insert(RbtNode* node, RbtTree* tree)
|
||||
{
|
||||
RbtNode* samenode = NULL;
|
||||
RbtNode* parent = NULL;
|
||||
|
||||
samenode = do_lookup(node->key, tree, &parent);
|
||||
if (samenode != NULL)
|
||||
return samenode;
|
||||
|
||||
node->left = node->right = NULL;
|
||||
set_color(RED, node);
|
||||
set_parent(parent, node);
|
||||
|
||||
if (parent == NULL)
|
||||
tree->root = node;
|
||||
else {
|
||||
set_child(tree, parent, node);
|
||||
}
|
||||
|
||||
while ((parent = get_parent(node)) != NULL && parent->color == RED) {
|
||||
RbtNode* grandpa = get_parent(parent); // grandpa must be existed
|
||||
// because root is black ,and parent is red,
|
||||
// parent can not be root of tree. and parent is red,so grandpa must be black
|
||||
if (parent == grandpa->left) {
|
||||
RbtNode* uncle = grandpa->right;
|
||||
if (uncle && get_color(uncle) == RED) {
|
||||
set_color(RED, grandpa);
|
||||
set_color(BLACK, parent);
|
||||
set_color(BLACK, uncle);
|
||||
node = grandpa;
|
||||
} else {
|
||||
if (node == parent->right) {
|
||||
rotate_left(parent, tree);
|
||||
node = parent;
|
||||
parent = get_parent(parent);
|
||||
}
|
||||
set_color(BLACK, parent);
|
||||
set_color(RED, grandpa);
|
||||
rotate_right(grandpa, tree);
|
||||
}
|
||||
|
||||
} else {
|
||||
RbtNode* uncle = grandpa->left;
|
||||
if (uncle && uncle->color == RED) {
|
||||
set_color(RED, grandpa);
|
||||
set_color(BLACK, parent);
|
||||
set_color(BLACK, uncle);
|
||||
node = grandpa;
|
||||
} else {
|
||||
if (node == parent->left) {
|
||||
rotate_right(parent, tree);
|
||||
node = parent;
|
||||
parent = get_parent(node);
|
||||
}
|
||||
set_color(BLACK, parent);
|
||||
set_color(RED, grandpa);
|
||||
rotate_left(grandpa, tree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_color(BLACK, tree->root);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int rbt_insert(RbtTree* tree, uintptr_t key, void* data)
|
||||
{
|
||||
RbtNode* node = rbtree_createnode(key, data);
|
||||
RbtNode* samenode = NULL;
|
||||
if (node == NULL)
|
||||
return -1;
|
||||
else
|
||||
samenode = __rbtree_insert(node, tree);
|
||||
if (samenode != NULL)
|
||||
return -2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void replace_node(RbtTree* t, RbtNode* oldn, RbtNode* newn)
|
||||
{
|
||||
if (oldn->parent == NULL) {
|
||||
t->root = newn;
|
||||
} else {
|
||||
if (oldn == oldn->parent->left)
|
||||
oldn->parent->left = newn;
|
||||
else
|
||||
oldn->parent->right = newn;
|
||||
}
|
||||
if (newn != NULL) {
|
||||
newn->parent = oldn->parent;
|
||||
}
|
||||
}
|
||||
|
||||
void delete_case1(RbtTree* tree, RbtNode* node)
|
||||
{
|
||||
if (node->parent == NULL)
|
||||
return;
|
||||
else
|
||||
delete_case2(tree, node);
|
||||
}
|
||||
|
||||
void delete_case2(RbtTree* tree, RbtNode* node)
|
||||
{
|
||||
if (get_color(sibling(node)) == RED) {
|
||||
node->parent->color = RED;
|
||||
sibling(node)->color = BLACK;
|
||||
if (node == node->parent->left) {
|
||||
rotate_left(node->parent, tree);
|
||||
} else {
|
||||
rotate_right(node->parent, tree);
|
||||
}
|
||||
}
|
||||
delete_case3(tree, node);
|
||||
}
|
||||
|
||||
void delete_case3(RbtTree* tree, RbtNode* node)
|
||||
{
|
||||
if (node->parent->color == BLACK && get_color(sibling(node)) == BLACK && get_color(sibling(node)->right) == BLACK && get_color(sibling(node)->left) == BLACK) {
|
||||
sibling(node)->color = RED;
|
||||
delete_case1(tree, node->parent);
|
||||
} else {
|
||||
delete_case4(tree, node);
|
||||
}
|
||||
}
|
||||
|
||||
void delete_case4(RbtTree* t, RbtNode* n)
|
||||
{
|
||||
if (get_color(n->parent) == RED && get_color(sibling(n)) == BLACK && get_color(sibling(n)->left) == BLACK && get_color(sibling(n)->right) == BLACK) {
|
||||
sibling(n)->color = RED; // sibling's two son is black ,so it can changed to red
|
||||
n->parent->color = BLACK;
|
||||
} else
|
||||
delete_case5(t, n);
|
||||
}
|
||||
|
||||
void delete_case5(RbtTree* t, RbtNode* n)
|
||||
{
|
||||
if (n == n->parent->left && get_color(sibling(n)) == BLACK && get_color(sibling(n)->left) == RED && get_color(sibling(n)->right) == BLACK) {
|
||||
sibling(n)->color = RED;
|
||||
sibling(n)->left->color = BLACK;
|
||||
rotate_right(sibling(n), t);
|
||||
} else if (n == n->parent->right && get_color(sibling(n)) == BLACK && get_color(sibling(n)->right) == RED && get_color(sibling(n)->left) == BLACK) {
|
||||
sibling(n)->color = RED;
|
||||
sibling(n)->right->color = BLACK;
|
||||
rotate_left(sibling(n), t);
|
||||
}
|
||||
delete_case6(t, n);
|
||||
}
|
||||
|
||||
void delete_case6(RbtTree* t, RbtNode* n)
|
||||
{
|
||||
sibling(n)->color = get_color(n->parent);
|
||||
n->parent->color = BLACK;
|
||||
if (n == n->parent->left) {
|
||||
assert(get_color(sibling(n)->right) == RED);
|
||||
sibling(n)->right->color = BLACK;
|
||||
rotate_left(n->parent, t);
|
||||
} else {
|
||||
assert(get_color(sibling(n)->left) == RED);
|
||||
sibling(n)->left->color = BLACK;
|
||||
rotate_right(n->parent, t);
|
||||
}
|
||||
}
|
||||
void __rbtree_remove(RbtNode* node, RbtTree* tree)
|
||||
{
|
||||
RbtNode* left = node->left;
|
||||
RbtNode* right = node->right;
|
||||
RbtNode* child = NULL;
|
||||
if (left != NULL && right != NULL) {
|
||||
RbtNode* next = get_min(right);
|
||||
node->key = next->key;
|
||||
node->data = next->data;
|
||||
node = next;
|
||||
}
|
||||
|
||||
assert(node->left == NULL || node->right == NULL);
|
||||
child = (node->right == NULL ? node->left : node->right);
|
||||
if (get_color(node) == BLACK) {
|
||||
set_color(get_color(child), node);
|
||||
delete_case1(tree, node);
|
||||
}
|
||||
replace_node(tree, node, child);
|
||||
if (node->parent == NULL && child != NULL) // node is root,root should be black
|
||||
set_color(BLACK, child);
|
||||
slab_free(&rbt_factory.rbtnode_ele_allocator, (void*)node);
|
||||
}
|
||||
|
||||
int rbt_delete(RbtTree* tree, uintptr_t key)
|
||||
{
|
||||
RbtNode* node = do_lookup(key, tree, NULL);
|
||||
if (node == NULL)
|
||||
return -1;
|
||||
else
|
||||
__rbtree_remove(node, tree);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user