首先红黑树是二叉树,故满足二叉树的所有规则,如父节点总大于左孩子并小于右孩子等。
其次红黑树有几点性质:
1.红黑树的节点必须是红色或黑色;
2.红黑树的根节点必须是黑色;
3.红黑树的红色节点的孩子必须是黑色节点(反过来不一定);
4.从根节点开始搜索任一条路径,每天路径上,黑色节点的数量必定相等;
5.为nil的叶子节点必须是黑色的。
当有新元素插入或移除旧元素时,红黑树平衡性有可能会发生破坏,为保持平衡,红黑树会通过三种方式对原树进行调整,分别是变色,左旋和右旋:
- 变色:
改变节点颜色比较容易理解,因为它违背了规则3。假设现在有个节点E,然后插入节点A和节点S,节点A在左子节点,S在右子节点,目前是平衡的。如果此时再插一个节点,那么就出现了不平衡了,因为红色节点的子节点必须为黑色,但是新插的节点是红色的。所以这时候就必须改变节点颜色了。所以我们将根的两个子节点从红色变为黑色(至于为什么都要变,下面插入的时候会详细介绍),将父节点会从黑色变成红色。可以用如下示意图表示一下:
- 左旋:通常左旋操作用于将一个向右倾斜的红色链接旋转为向左链接。
左旋有个很萌萌哒的动态示意图,可以方便理解:
- 右旋:
右旋也有个萌萌的动态图:
红黑树的插入元素必须是红色的,是因为插入黑色时,插入节点所在的路径上多了一个黑色节点,必定违反性质4,但插入红色节点,可以大大减少发生该情况的概率。
1⃣️ 对于红黑树的插入,分如下三种情况讨论
1.插入节点的父节点为黑色节点,无需其他操作,红黑树仍满足性质;
2.插入节点的父亲节点为红色节点时:
2.1. 插入节点的叔叔节点也是红色,则
- 将父亲节点设置为黑色;
- 将叔叔节点设置为黑色;
- 将祖父节点设置为红色;
- 将祖父节点当成新的“插入节点”,根据其父节点和叔叔节点继续递归考察。
2.2. 当前节点的叔叔节点是黑色,该节点是父节点的右孩子,则
- 将父节点当作新的“当前节点“;
- 以新的当前节点为支点进行左旋;
2.3 当前节点的叔叔节点是黑色,该节点上父亲节点的左孩子,则
- 将父节点设置为黑色;
- 将祖父设置成红色;
- 以祖父为支点进行右旋。