数据结构 —— 红黑树|8月更文挑战

117 阅读5分钟

这是我参与8月更文挑战的第12天,活动详情查看:8月更文挑战

二叉平衡树的严格平衡策略以牺牲建立查找结构(插入,删除操作)的代价,换来了稳定的O(logN) 的查找时间复杂度。但是这样做是否值得呢? 能不能找一种折中策略,即不牺牲太大的建立查找结构的代价,也能保证稳定高效的查找效率呢? 答案就是:红黑树。

红黑树是一种含有红、黑结点,并能自平衡的二叉查找树。高度为 logN。其性质如下:

  • 每个结点或是红色的,或是黑色的
  • 根节点是黑色的
  • 每个叶子节点(NIL)是黑色的
  • 如果一个节点是红色的,则它的两个子节点都是黑色的
  • 任意一结点到每个叶子结点的路径都包含数量相同的黑节点

正是红黑树的这5条性质,使一棵n个结点的红黑树始终保持了logN的高度,从而也就解释了“红黑树的查找、插入、删除的时间复杂度最坏为O(logN)”这一结论成立的原因。

Red-BlackTree.jpg

效率总结

  • 查找:最好情况下时间复杂度为O(logN),但在最坏情况下比AVL要差一些,但也远远好于BST

  • 插入/删除:改变树的平衡性的概率要远远小于AVL(RBT不是高度平衡的)

    因此需要旋转操作的可能性要小,且一旦需要旋转,插入一个结点最多只需旋转2次,删除最多只需旋转3次(小于AVL的删除操作所需要的旋转次数)。虽然变色操作的时间复杂度在O(logN),但是实际上,这种操作由于简单所需要的代价很小

1 左旋

左旋.jpg

  • 逆时针旋转两个节点,让一个节点被其右子节点取代,而该节点成为右子节点的左子节点
  • 对x进行左旋,意味着"将x变成一个左节点"
  • 左旋条件:两个连续红节点,并且叔叔节点是黑色 , 下面的红色节点在右子树

1.1 情况1

如果当前节点是右子树,并且父节点是左子树。形如:(900是新插入节点)

左旋条件情况1.png

要根据父节点左旋【899】(根据谁左旋,谁就变成子节点):

左旋条件情况1流程.gif

【900】的左子树挂到 【899】的右子树上 , 【899】变为子节点 , 【900】变为父节点此时不变色

1.2 情况2

如果当前节点是右子树,并且父节点是右子树。形如:(【100】是当前节点)

左旋条件情况2.png

根据祖父节点左旋【56】(根据谁左旋,谁就变成子节点):

左旋条件情况2流程.gif

【56】变为子节点,【89】变为父节点,【89】的左子树 挂到 【56】的右子树。同时: 父节点变黑(【89】变黑),祖父节点变红(【56】变红 )。

2 右旋

右旋.jpg

  • 顺时针旋转两个节点,让一个节点被其左子节点取代,而该节点成为左子节点的右子节点
  • 对x进行左旋,意味着"将x变成一个左节点"
  • 右旋条件:两个连续红节点,并且叔叔节点是黑色 , 下面的红色节点在左子树

2.1 情况1

如果当前节点是左子树,并且父节点也是右子树。形如:(【8000】是当前节点)

右旋条件情况1.png

根据父节点右旋【9000】(根据谁右旋,谁就变成子节点):

右旋条件情况1流程.gif

【9000】变为子节点,【8000】变为父节点,【8000】的右子树 挂到 【9000】的左子树,此时不变色。

2.2 情况2

如果当前节点是左子树,并且父节点也是左子树。形如:(【899】是当前节点)

右旋条件情况2.png

根据祖父节点右旋【1000】(根据谁右旋,谁就变成子节点):

右旋条件情况2流程.gif

【1000】变为子节点,【900】变为父节点,【900】的右子树 挂到 【1000】的左子树 同时: 父节点变黑(【900】变黑),祖父节点变红(【1000】变红)。

3 变色

如果当前节点的父亲节点和叔叔节点均是红色,那么执行以下变色操作:

父 --> 黑 叔 --> 黑 爷 --> 红

无法通过变色而进行旋转的四种场景

3.1 场景一:左左节点旋转

这种情况下,父节点和插入的节点都是左节点,如下图(旋转原始图1)这种情况下,我们要插入节点 65。规则如下:以祖父节点【右旋】,搭配【变色】。

左左节点旋转.png

按照规则,步骤如下:

左左节点旋转步骤.jpeg

3.2 场景二:左右节点旋转

这种情况下,父节点是左节点,插入的节点是右节点,在旋转原始图 1 中,我们要插入节点 67。规则如下:先父节点【左旋】,然后祖父节点【右旋】,搭配【变色】。按照规则,步骤如下:

左右节点旋转.png

3.3 场景三:右左节点旋转

这种情况下,父节点是右节点,插入的节点是左节点,如下图(旋转原始图 2)这种情况,我们要插入节点 68。规则如下:先父节点【右旋】,然后祖父节点【左旋】,搭配【变色】。

右左节点旋转.png

按照规则,步骤如下:

右左节点旋转步骤.jpeg

3.4 场景四:右右节点旋转

这种情况下,父节点和插入的节点都是右节点,在旋转原始图 2 中,我们要插入节点 70。规则如下:以祖父节点【左旋】,搭配【变色】。按照规则,步骤如下:

右右节点旋转.png