#include "rbt.h"
bool Init_RBT(rb_root *T)
{
if(T == NULL)
{
T = (rb_root*)malloc(sizeof(rb_root));
if( T == NULL)
return false;
T->root = NULL;
return true;
}
return false;
}
NodeStatus RbtLeftRotate(Node *x, rb_root *T)
{
if( T == NULL)
return False;
//parent
if(x->rchild->parent = x->parent)
{
if(x->parent->rchild == x)
x->parent->rchild = x->rchild;
else
x->parent->lchild = x->rchild;
}
else
T->root = x->rchild;
x->parent = x->rchild;
//rchild
if(x->rchild->lchild == NULL)
x->rchild = NULL;
else
{
x->rchild->lchild->parent = x;
x->rchild = x->rchild->lchild;
}
x->parent->lchild = x;
return OP_SUCCESS;
}
NodeStatus RbtRightRotate(Node *x, rb_root *T)
{
if( T == NULL)
return False;
//parent
if(x->lchild->parent = x->parent)
{
if(x->parent->rchild == x)
x->parent->rchild = x->lchild;
else
x->parent->lchild = x->lchild;
}
else
T->root = x->lchild;
x->parent = x->lchild;
//rchild
if(x->lchild->rchild == NULL)
x->lchild = NULL;
else
{
x->lchild->rchild->parent = x;
x->lchild = x->lchild->rchild;
}
x->parent->rchild = x;
return OP_SUCCESS;
}
NodeStatus find_next(Node *T, Node *Next)
{
if(T == NULL)
return False;
if(NULL == T->parent && NULL == T->rchild && NULL == T->lchild)
return RootNode;
if(NULL == T->rchild && NULL == T->lchild)
return NilNode;
else if(NULL == T->rchild)
return NoRchild;
Next = T->rchild;
while(NULL != Next->lchild)
Next = Next->lchild;
return OP_SUCCESS;
}
NodeStatus find_prev(Node *T, Node *prev)
{
if(T == NULL)
return False;
if(NULL == T->parent && NULL == T->rchild && NULL == T->lchild)
return RootNode;
if(NULL == T->rchild && NULL == T->lchild)
return NilNode;
else if(NULL == T->lchild)
return NoLchild;
prev = T->lchild;
while(NULL != prev->rchild)
prev = prev->rchild;
return OP_SUCCESS;
}
NodeStatus InsertNode(int key_value, rb_root *T)
{
if(T == NULL)
Init_RBT(T);
Node *x = (Node*)malloc(sizeof(Node));
x->lchild = NULL;
x->rchild = NULL;
x->parent = NULL;
x->color = red;
x->key = key_value;
if(T->root == NULL)
{
T->root = x;
x->color = black; //root node must be black
return OP_SUCCESS;
}
Node *next = T->root;
while(1)
{
if(key_value == next->key)
{//same value Node ignore or add Node->KeyTimes + 1
free(x);
return SameKey;
}
if(key_value < next->key)
{
if(NULL == next->lchild)
{//nil set
next->lchild = x;
x->parent = next;
Insert_col_fix(x, T);
return OP_SUCCESS;
}
next = next->lchild;
}
if(key_value > next->key)
{
if(NULL == next->rchild)
{
next->rchild = x;
x->parent = next;
Insert_col_fix(x, T);
return OP_SUCCESS;
}
next = next->rchild;
}
}
return False;
}
NodeStatus Insert_col_fix(Node *node, rb_root *root)
{
if(NULL == root || NULL == node)
return False;
/* modify from the linux-kernel 2.6.9 /lib/rntree.c--rb_insert_color function */
Node *parent, *gparent;
while ((parent = node->parent) && parent->color == red)
{
gparent = parent->parent;
if (parent == gparent->lchild)
{
{
register Node *uncle = gparent->rchild;
if (uncle && uncle->color == red)
{//node red ,parent lchild and red ,uncle rchild and red
uncle->color = black;
parent->color = black;
gparent->color = red;
node = gparent; //set node to gparent
continue;
}
}
if (parent->rchild == node)
{//node red and rchild, parent red and lchild
register Node *tmp;
RbtLeftRotate(parent, root); //left_rotate the parent
tmp = parent;
parent = node;
node = tmp;
}
parent->color = black;
gparent->color = red;
RbtRightRotate(gparent, root);
} else {
{
register Node *uncle = gparent->lchild;
if (uncle && uncle->color == red)
{//parent red and rchild,uncle red and lchild,node red
uncle->color = black;
parent->color = black;
gparent->color = red;
node = gparent;
continue;
}
}
if (parent->lchild == node)
{//node red and lchild,parent red and rchild
register Node *tmp;
RbtRightRotate(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
parent->color = black;
gparent->color = red;
RbtLeftRotate(gparent, root);
}
}
root->root->color = black;
return OP_SUCCESS;
}
NodeStatus find_key_node(Node *find, int key, rb_root *T)
{
if(NULL == T)
return False;
if(NULL == T->root)
return EmptyTree;
find = T->root;
while (key != find->key)
{
if(key > find->key)
{
if(find->rchild == NULL)
return NoRchild;
find = find->rchild;
}
else
{
if(find->lchild == NULL)
return NoLchild;
find = find->lchild;
}
}
return OP_SUCCESS;
}
NodeStatus del_node(int key, rb_root *T)
{
if(NULL == T)
return False;
Node *find = NULL;
NodeStatus Ret = find_key_node(find, key, T);
if(OP_SUCCESS != Ret)
return False;
Node *NextNode = NULL, *child, *parent;
NodeColor color = def;
if(find->rchild && find->lchild)
{
if(find_next(find, NextNode))
return False;
child = NextNode->rchild;
parent = NextNode->parent;
color = NextNode->color;
if(child)
child->parent = parent;
if(parent->lchild == NextNode)
parent->lchild = child;
else
parent->rchild = child;
find->key = NextNode->key;
free(NextNode);
}
else
{
if(!find->lchild)
child = find->rchild;
else if(NoRchild == Ret)
child = find->lchild;
parent = find->parent;
color = find->color;
if(child)
child->parent = parent;
if(parent)
{
if(parent->lchild == find)
parent->lchild = child;
else
parent->rchild = child;
}
else
T->root = child;
free(find);
}
if(black == color)
return del_col_fix(child, parent, T);
return OP_SUCCESS;
}
NodeStatus del_col_fix(Node *node, Node *parent, rb_root *T)
{
Node *brother;
while((!node || node->rchild == black) && node != T->root)
{//node is nilnode or node rchild is black ,node is not root
if (parent->lchild == node)
{
brother = parent->rchild;
if (brother->color == red)
{//brother is red
brother->color = black;
parent->color = red;
RbtLeftRotate(parent, T);
brother = parent->rchild; //update brother
}
if ((!brother->rchild || brother->rchild->color == black)\
&& (!brother->lchild || brother->lchild->color == black))
{//brother's rchild and lchild are nil or black,brother is black
brother->color = red;
node = parent; //if parent is red ,jump loop,set node to black
parent = node->parent;
}
else
{
if (!brother->rchild || brother->rchild->color == black)
{//brother(black) rchild is black ,lchild is red
brother->color = red;
brother->lchild->color = black;
RbtRightRotate(brother, T);
brother = parent->rchild;
}
//brother(black) rchild is red
brother->color = parent->color;
parent->color = black;
brother->rchild->color = black;
RbtLeftRotate(parent, T);
break;
}
}
else
{
brother = parent->lchild;
if (brother->color == red)
{
brother->color = black;
parent->color = red;
RbtRightRotate(parent, T);
brother = parent->lchild;
}
if((!brother->lchild || brother->lchild->color == black)\
&& (!brother->rchild || brother->rchild->color == black))
{
brother->color = red;
node = parent;
parent = node->parent;
}
else
{
if(!brother->lchild || brother->lchild->color == black)
{
brother->color = red;
brother->rchild->color = black;
RbtLeftRotate(brother, T);
brother = parent->lchild;
}
brother->color = parent->color;
parent->color = black;
brother->lchild->color = black;
RbtRightRotate(parent, T);
break;
}
}
if(node->color == red)
node->color = black;
}
}
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef enum{
red,
black,
def
}NodeColor;
typedef struct RBTreeNode{
NodeColor color;
int key;
struct RBTreeNode *rchild, *lchild, *parent;
}Node, *RBTree;
typedef struct T_root{
RBTree root;
}rb_root;
typedef enum {
OP_SUCCESS = 0,
RootNode,
NilNode,
NoRchild,
NoLchild,
SameKey,
EmptyTree,
False
}NodeStatus;
NodeStatus Insert_col_fix(Node *node, rb_root *root);
NodeStatus del_col_fix(Node *node, Node *parent, rb_root *T);
红黑树的特性:
1.节点是红色或黑色。
2.根节点是黑色。
3.每个叶子节点都是黑色的空节点(NIL节点)。
4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
5.从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
插入时总是要考虑它的叔叔,删除时总要考虑它的兄弟。而且插入时维护的主要是颜色(性质4),而删除时维护的主要是黑色结点数量(性质5)
详情参考
https://blog.youkuaiyun.com/weewqrer/article/details/51866488
和Linux源码/lib/rbtree.c