【数据结构】红黑树理解

红黑树

红黑树是一个含有红黑节点并能够自平衡的二叉查找树

性质

必须满足五个性质

  1. 每个节点要么是黑色,要么是红色
  2. 根节点是黑色
  3. 每个叶子节点(NIL)是黑色的
  4. 每个红色节点的两个子节点一定是黑色的
  5. 任意一节点到其自身的每个叶子节点的路径都包含相同数量的黑色节点

由性质五可推出:如果一个节点存在黑子节点,那么该节点一定有两个子节点

下图是一个基础的红黑树结构

基础红黑树结构

红黑树并不一定是完美的平衡二叉查找树,如上图左子树就比右子树高,但是它符合性质五:任意一节点到每个叶子节点的路径都包含相同数量的黑色节点 ,称这种平衡为黑色完美平衡

我们把正在处理的节点称为当前节点(D),他的父亲叫做父节点(F),父亲的父亲叫做祖父节点(P),父亲的兄弟叫做叔叔节点(V),当前节点的兄弟叫做兄弟节点(K)

自平衡

红黑树自平衡的三步操作

变色:由红色节点向黑色节点转化,或者由黑色节点向红色节点转化

左旋:以某个节点作为支点(旋转节点),其右子结点变为旋转节点的父节点,右子结点的左子节点变为旋转节点的右子节点,左子节点保持不变

右旋:以某个节点作为支点(旋转节点),其左子节点变为旋转节点的父节点,左子节点的右子节点变为旋转节点的左子节点,右子节点保持不变

左旋
在这里插入图片描述

以上只是对左旋右旋的简单示例,并没有达到 黑色完美平衡,至于是红黑树是如何自平衡的则需要看插入操作

查询

  1. 从根节点开始查找,把根节点设置为当前节点;
  2. 若当前节点为空,返回null
  3. 若当前节点不为空,用当前节点的key跟查找key作比较
  4. 若当前节点key等于查找key,那么该key就是查找目标,返回当前节点
  5. 若当前节点key大于查找key,把当前节点的左子节点设置为当前节点,重复步骤2
  6. 若当前节点key小于查找key,把当前节点的右子节点设置为当前节点,重复步骤2

查询

插入

  1. 从根节点开始查找,把根节点作为当前节点
  2. 若当前节点为null则插入,结束
  3. 若当前节点key等于查找key,那么该key所在节点就是插入节点,更新节点的值,结束
  4. 若当前节点key大于查找key,把当前节点的左子节点设置为当前节点,重复步骤2
  5. 若当前节点key小于查找key,把当前节点的右子节点设置为当前节点,重复步骤2

插入的节点一定是红色的,因为如果插入节点的父节点是黑色的,那么插入红节点不会破坏黑色完美平衡(性质五),如果插入的是黑色,那么插入位置所在的子树黑色总是多1,必须要自平衡

插入分成了几种情况

(一)红黑树为空数,将插入节点设置为根节点并置为黑色

(二)插入节点的Key已存在,则更新已存在节点的Value为插入节点的Value

(三)插入节点的父节点是黑色的,则直接插入,不会影响平衡

(四)插入节点的父节点是红色的

由性质二可知:根节点是黑色的。如果插入节点的父节点是红色的,那么插入节点的父节点不可能是根节点,也就是说插入节点一定会有祖父节点,并且祖父节点是黑色的,记住这点,后续的自旋操作需要祖父节点参与。

定义 I 为插入节点,P 为祖父节点,F 为父节点

4.1 叔叔节点存在并且为红节点

已知祖父节点是黑色,所以现在插入子树的结构是黑红红

  • 将父节点(F)和叔叔节点(V)设置为黑色
  • 将祖父节点(P)设置为红色
  • 将祖父节点设置为当前插入节点

插入4.1

这种情况,如果P节点的父节点是黑色,那么就不需要再做处理。若果P节点的父节点是红色的,那么红黑树就不平衡了,需要把P设置为插入节点继续做自平衡。如果P节点就是根节点那么需要将P节点设置为黑色,这个时候就变成了黑黑红,也是唯一一种会增加黑节点数的场景。

4.2 叔叔节点不存在或者为黑节点,并且插入节点的父节点是祖父节点的左子节点

4.2.1 插入节点是其父节点的左子节点(LL)

Left-Left 父节点和插入节点都红色的是左子节点

  • 将父节点(F)设置为黑色
  • 将祖父节点(P)设置为红色
  • 对祖父节点(P)进行右旋

插入4.2.1

这种情况,父节点为红节点,那么叔叔节点非红即为NIL。因为如果叔叔节点为黑节点,而父结点为红结点,那么叔叔结点所在的子树的黑色节点就比父节点所在子树的多了,违背了性质五。

4.2.2 插入节点是其父节点的右子节点(LR)

Left-Right 父节点是红左子节点,插入节点是红右子节点

  • 对父节点(F)进行左旋
  • 把父节点(F)设置为插入结点,得到情景4.2.1
  • 进行情景4.2.1的处理

插入4.2.2

4.3 叔叔节点不存在或者为黑节点,并且插入节点的父节点是祖父节点的右节点

4.3.1 插入节点是其父节点的右子节点(RR)

Right-Right 父节点和插入节点都红色的是右子节点

其实就是和LL做相反操作

  • 将父节点(F)设为黑色
  • 将祖父节点(P)设为红色
  • 对祖父节点(P)进行左旋

插入4.3.1

4.3.2 插入节点是其父节点的左子节点(RL)

Right-Left 父节点是红右子节点,插入节点是红左子节点

其实就是和LR做相反操作

  • 对父节点(F)进行右旋
  • 把父节点(F)设置为插入结点,得到情景4.3.1
  • 进行情景4.3.1的处理

插入4.3.2

练习

在这里插入图片描述
红黑树的简单实现 JAVA版

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章