一. 简介
-
红黑树是一种含有
红黑结点
并能自平衡
的二叉查找树。满足如下性质:性质1:每个节点要么是黑色,要么是红色。
性质2:根节点是黑色。
性质3:每个叶子节点(NIL)是黑色。
性质4:每个红色结点的两个子结点一定都是黑色。
性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。 -
自平衡的方式
- 左旋:以某个结点作为支点(旋转结点),其右子结点变为旋转结点的父结点,右子结点的左子结点变为旋转结点的右子结点,左子结点保持不变。
- 右旋:以某个结点作为支点(旋转结点),其左子结点变为旋转结点的父结点,左子结点的右子结点变为旋转结点的左子结点,右子结点保持不变。
- 变色:结点的颜色由红变黑或由黑变红。
- 左旋:以某个结点作为支点(旋转结点),其右子结点变为旋转结点的父结点,右子结点的左子结点变为旋转结点的右子结点,左子结点保持不变。
二. 红黑树的查找
- 从根结点开始查找,把根结点设置为当前结点;
- 若当前结点为空,返回null;
- 若当前结点不为空,用当前结点的key跟查找key作比较;
- 若当前结点key等于查找key,那么该key就是查找目标,返回当前结点;
- 若当前结点key大于查找key,把当前结点的左子结点设置为当前结点,重复步骤2;
- 若当前结点key小于查找key,把当前结点的右子结点设置为当前结点,重复步骤2;
三. 红黑树的插入
- 步骤(查找插入的位置、插入后自平衡)
- 从根结点开始查找;
- 若根结点为空,那么插入结点作为根结点,结束。
- 若根结点不为空,那么把根结点作为当前结点;
- 若当前结点为null,返回当前结点的父结点,结束。
- 若当前结点key等于查找key,那么该key所在结点就是插入结点,更新结点的值,结束。
- 若当前结点key大于查找key,把当前结点的左子结点设置为当前结点,重复步骤4;
- 若当前结点key小于查找key,把当前结点的右子结点设置为当前结点,重复步骤4;
- 插入前景分析
插入结点应该是红色;
约定叫法:
-
情景1:红黑树为空树
把插入结点作为根结点并设为黑色。 -
情景2:插入结点的Key已存在
插入前红黑树已是平衡的,则直接把插入结点设置为将要替代结点的颜色,再把结点的值更新。 -
情景3:插入结点的父结点为黑结点
用于插入的结点是红色的,当插入结点的父结点为黑色时,不会影响红黑树的平衡,故直接插入即可。 -
情景4:插入结点的父结点为红结点
性质2:根结点是黑色。如果插入的父结点为红结点,那么该父结点不可能为根结点,所以插入结点总是存在祖父结点。情景4.1:叔叔结点存在并且为红结点
由性质4可知,祖父结点肯定为黑结点,则此时该插入子树的红黑层数的情况是:黑红红。故需要把其改为:红黑红。
将P和S设置为黑色;
将PP设置为红色;
把PP设置为当前插入结点。
此时,PP结点设为红色了,如果PP的父结点是黑色,那么无需再做任何处理;但如果PP的父结点是红色,根据性质4,此时红黑树已不平衡了,所以还需要把PP当作新的插入结点,继续做插入操作自平衡处理,直到平衡为止。插入情景4.2:叔叔结点不存在或为黑结点,并且插入结点的父亲结点是祖父结点的左子结点
略,不再介绍了。。。。。
-
四. 红黑树的删除
-
步骤
查找目标结点;
删除后自平衡。 -
前景
情景1:若删除结点无子结点,直接删除
情景2:若删除结点只有一个子结点,用子结点替换删除结点
情景3:若删除结点有两个子结点,用后继结点(大于删除结点的最小结点)替换删除结点