为了解决二叉树多次插入新结点而导致的不平衡–> 诞生了红黑树
一、红黑树的性质(红黑树是一种自平衡的二叉查找树)
- 每个结点是红的或黑的
- 根结点是黑的
- 每个叶子结点是黑的
- 如果一个结点是红的,它的两个儿子都是黑的
- 对于每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点
红黑树中有key,value。结点上我们可以看到的数字是key,value一般不会显示出来
// 定义红黑树的结点
typedef int KEY_TYPE;
typedef struct _rbtree_node {
unsigned char color;
struct _rbtree_node* left;
struct _rbtree_node* right;
struct _rbtree_node* parent; // 用于旋转
KEY_TYPE key;
void* value; // 万能指针
} rbtree_node;
// 定义红黑树(红黑树是由多个结点组成的)
// 树类似于链表(有头结点即可),树有根结点即可
typedef struct _rbtree {
rbtree_node* root;
rbtree_node* nil; // 一个通用的叶子结点,让所有叶子结点都指向该结点,通过这一个结点来判断是否是叶子结点即可
} rbtree;
二、红黑树自平衡
当插入或删除结点的时候,红黑树的规则可能被打破,这时候需要做一些调整来维持我们的规则,调整的方法有两种:变色+旋转
红黑树结点旋转
- 左旋
相当于将下图蓝色圈起来部分向左下方拉,变成y结点的左结点,y原本的左节点接到x上,x原本的父结点变为y的父节点
- 右旋
相当于将蓝色圈起来部分向右下拉,变成x结点的右结点,x原本的右结点接到y上,y原本的父结点变成x的父结点