本文章为个人学习笔记,仅供参考(文末有代码)
1.什么是红黑树?
****红黑树是一种自平衡的二叉查找树,是一个高效查找的数据结构。
2.红黑树的特征都有哪些?
****1. 每一个结点都有一个颜色,要么为红色,要么为黑色;
****2. 树的根结点为黑色;
****3. 树中不存在两个相邻的红色结点(即红色结点的父结点和孩子结点均不能 是红色)
****4. 从任意一个结点(包括根结点)到其任何后代 NULL 结点(默认是黑色的)的每条路径都具有相同数量的黑色结点。
3.红黑树的左旋与右旋(叶子节点已隐藏)
4.红黑树的插入!
****前提条件:
1.在我们每插入一个点之前,原本的红黑树就已经达到平衡条件。
2.一般为了不破坏红黑树的平衡条件,我们把插入的节点赋为红色。进而再通过旋转方式使之达到平衡。
主要是第三点和第四点:
父子节点不能都是红颜色
每个节点对应的黑高相同(需要考虑父亲,祖父,叔父节点)
父节点红,叔父节点红---------------父,叔父变黑,祖父变红
父节点红,叔父节点黑
****1.当前节点为右子树---------------当前节点左旋(父节点左旋一样的)
***2.当前节点为左子树---------------父节点右旋,父节点变黑,祖父节点变红
以上为三种转换情况,如果转换后祖父节点和其祖父的父节点都为红色,则循环直至平衡为止
5.红黑树的删除
不考虑颜色的时候是这样的
***1.没有子树--------
***2.只有左子树或者右子树--------
3.有左子树或者右子树
红黑树的删除
当前结点是父结点的左子树的情况
1.当前结点的兄弟结点是红色的
2.当前结点的兄弟结点是黑色的,而且兄弟结点的两个孩子结点都是黑色的
3.当前结点的兄弟结点是黑色的,而且兄弟结点的左孩子是红色的,右孩子是黑色的
4.当前结点的兄弟结点是黑色的,而且兄弟结点的右孩子是红色的
对应1.操作(删除786):小弟节点右旋,兄弟节点变黑,祖父节点变红
对应2.操作(删除62):兄弟节点变红,父节点的兄弟节点变红,父亲节点的兄弟节点变红
对应操作:
#define RED 0
#define BLACK 1
typedef int KEY_TYPE;
typedef struct _rbtree_node {
//rbtree
unsigned char color;
struct rbtree_node *parent;
struct rbtree_node *left;
struct rbtree_node *right;
// end
KEY_TYPE key;
// value
//
} rbtree_node;
struct rbtree {
rbtree_node *root;
rbtree_node *nil; // NULL
};
// rotate
void rbtree_left_rotate(rbtree *T, rbtree_node *x) {
// NULL --> T->nil
if (x == T->nil) return ;
// 1
rbtree_node *y = x->right;
x->right = y->left;
if (y->left != T->nil) {
y->left->parent = x;
}
// 2
y->parent = x->parent;
if (x->parent == T->nil) {
T->root = y;
} else if (x == x->parent->left) {
x->parent->left = y;
} else {
x->parent->right = y;
}
// 3
y->left = x;
x->parent = y;
}
// x --> y, y -->x
// left --> right, right --> left
void rbtree_right_rotate(rbtree *T, rbtree_node *y) {
// NULL --> T->nil
if (y == T->nil) return ;
// 1
rbtree_node *x = y->left;
y->left = x->right;
if (y->left != T->nil) {
y->left->parent = x;
}
// 2
y->parent = x->parent;
if (x->parent == T->nil) {
T->root = y;
} else if (x == x->parent->left) {
x->parent->left = y;
} else {
x->parent->right = y;
}
// 3
y->left = x;
x->parent = y;
}
void rbtree_insert_fixup(rbtree *T, rbtree_node *z) {
//
// z->color == RED
// z->parent->color == RED
// z--> RED
while (z->parent->color == RED) { //
if (z->parent == z->parent->parent->left) {
y = z->parent->parent->right; //
if (y->color == RED) {
z->parent->color = BLACK;
z->parent->parent->color = RED;
y->color = BLACK;
z = z->parent->parent; //
} 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);
}
}
}
}
void rbtree_insert(rbtree *T, rbtree_node *z) {
rbtree_node *y = T->nil;
rbtree_node *x = T->root;
while (x != T->nil) {
y = x;
if (z->key < x->key) {
x = x->left;
} else if (z->key > x->key) {
x = x->right;
} else { //Exist
}
}
z->parent = y;
if (y == T->nil) {
T->root = z;
} else if (z->key < y->key) {
y->left = z;
} else {
y->right = z;
}
// z -->
z->color = RED;
z->left = T->nil;
z->right = T->nil;
//
}