红黑树
发明原因
针对于平衡二叉树,插入/删除很容易破坏“平衡”特性,需要频繁调整树的形态。
红黑树适合频繁插入删除的场景,实用性更强。
红黑树的性质
- 结点是红色或者黑色
- 根结点是黑色
- 叶子节点是黑色
- 不存在相邻的红结点
- 对于每个结点,从该结点到可到达的叶子结点的所有路径上包含相同数目的黑结点
口诀:左根右,根叶黑,不红红,黑路同
红黑树的结点旋转
红黑树的定义以及插入的实现源码
typedef int KEY_TYPE;
#define RED 0
#define BLACK 1
#define RBTREE_ENTRY(name, type)
struct name
{
struct type *right;
struct type *left;
struct type *parent;
unsigned char color;
};
typedef struct _rbtree_node
{ //
KEY_TYPE key;
void *value;
#if 1
struct _rbtree_node *right;
struct _rbtree_node *left;
struct _rbtree_node *parent;
unsigned char color;
#else
RBTREE_ENTRY(, _rbtree_node)
node;
#endif
} rbtree_node;
typedef struct _rbtree
{
struct _rbtree_node *root;
struct _rbtree_node *nil; // 所有的叶子结点
} rbtree;
// 左旋
void rbtree_left_rotate(rbtree *T, rbtree_node *x)
{
rbtree_node *y = x->right;
x->right = y->left;
// 如果y的左子树不是叶子结点,才需要修改,否则不需要
if (y->left != T->nil)
y->left->parent = x;
y->parent = x->parent;
// x的parent的几种情况
// 1. x是根节点
// 2. x是父节点的左子树还是右子树
if (x->parent == T->nil)
T->root = y;
else
{
if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
}
y->left = x;
x->parent = y;
}
// 右旋
void rbtree_right_rotate(rbtree *T, rbtree_node *y)
{
rbtree_node *x = y->left;
// x->right = y->left;
y->left = x->right;
// 如果x的右子树不是叶子结点,才需要修改,否则不需要
if (x->right != T->nil)
x->right->parent = y;
x->parent = y->parent;
// y的parent的几种情况
// 1. y是根节点
// 2. y是父节点的左子树还是右子树
if (y->parent == T->nil)
T->root = x;
else
{
if (y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
}
x->right = y;
y->parent = x;
}
void rbtree_insert_fixup(rbtree *T, rbtree_node *z)
{
// z == RED 插入时其父是红色 才需要调整
while (z->parent->color == RED)
{
if (z->parent == z->parent->parent->left)
{
// y是z的叔结点
rbtree_node *y = z->parent->parent->right;
// 如果叔叔是红色的
if (y->color == RED)
{
z->parent->color == BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent; // z是红色
}
// 如果叔叔是黑色的
else
{
if (z == z->parent->right)
{
z = z->parent;
rbtree_left_rotate(T, z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
rbtree_right_rotate(T, z->parent->parent);
}
}
else
{
}
}
}
// 在T中插入z
void rbtree_insert(rbtree *T, rbtree_node *z)
{
rbtree_node *x = T->root;
rbtree_node *y = T->nil;
while (x != T->nil)
{
y = x;
if (z->key < x->key)
x = x->left;
else if (z->key > x->key)
x = x->right;
else // 红黑树插入如果有相同结点:取决于业务
return;
}
if (y == T->nil)
{
T->root = z;
}
else
{
// 进而考虑z插到y的左子树还是右子树
if (y->key > z->key)
{
y->left = z;
}
else
{
y->right = z;
}
}
z->parent = y;
z->left = T->nil;
z->right = T->nil;
z->color = RED;
// 调整树
rbtree_insert_fixup(T, z);
}