红黑树之一(基本性质,插入节点)

平衡二叉树(AVL)是一种具有很好的性能的排序二叉树,但是也并不完美。如果所需要维护数据变化也比较频繁,这就需要经常对ALV树进行调整,由于平衡二叉树对其子树的限制太严格,因而进行插入或者删除时经常需要对树进行调整,而且插入时需要调整的子树可能就是树本身,这就需要较长的时间来查找需要调整的子树的根节点;而对于删除操作情况可能更糟,极端情况下,甚至需要递归的对每层进行调整一直调整到根节点。比如:

《红黑树之一(基本性质,插入节点)》

如果要在上图中插入一个新的节点8,则它将成为节点7的右孩子,根据AVL树的性质,以节点7、13、25、50为根节点的子树的高度都变大,但是以节点7、13、25为根的子树的平衡因子在插入后仍满足AVL树的要求,因而不需要调整,但是以节点50为根的树的高度变大后,其平衡因子不再满足ALV树的要求,因而需要进行调整。也就说说在上图所述的情形下,插入后需要一直回溯到原树的根节点,并对其进行调整后,才能完成整个插入操作。

《红黑树之一(基本性质,插入节点)》

如果要从上图中删除节点7,则如果想要删除后的仍为AVL树,则需要调整两次,第一次调整以节点25为根的子树,第二次调整以节点50为根的“子”树。(为了简单起见,只是给出了需要调整两次的示例,但已经足以展示需要递归的进行多次调整的情形。)

因而实际中更为常用的是另一种排序二叉树–红黑树,它也是一种在二叉树上添加了限制的树,它实际上也对每个节点的子树做了限制,实际上是另一种“平衡二叉树”。

一、基本概念

红黑树是一种二叉排序树(或者说查找树),但是它在每个节点上增加了一个域表示该节点的颜色,节点只有两种颜色Red或Black,因此该树被称为红黑树。一棵满足如下限制的二叉查找树就是一棵红黑树,或者说红黑树必须具备如下性质:

  1. 每个节点要么是红的,要么是黑的。
  2. 根节点是黑的。
  3. 所有叶节点都是黑色(红黑树引入了NULL节点来作为其叶节点,需要注意的是一般在画图时都会忽略这些NULL节点)。
  4. 如果一个节点是红的,那么它的俩个儿子都是黑的。
  5. 对于任一节点而言,它到它的任意一个叶结点的每一条路径都包含相同数目的黑结点。

这五个性质的最重要的结果就是确保了从红黑树的根节点到其任意一个叶子节点的路径中,最长路径的长度最多是最短路径长度的二倍。其原因在于:

红黑树的第4条性质保证了这些路径中的任意一条都不存在连续的红节点,而红黑树的第5条性质又保证了所有的这些路径上的黑色节点的数目相同。因而最短路径必定是只包含黑色节点的路径,而最长路径为红黑节点互相交叉的路径,由于所有的路径的起点必须是黑色的,而红色节点又不能连续存在,因而最长路径的长度为全为黑色节点路径长度的二倍。

红黑树的这一特性也意味着红黑树大体上是平衡的,其高度不会“太高”,因而可以获得较好的插入、删除、查找性能。
红黑树的第3条性质的作用不那么明显,来看一棵树:

《红黑树之一(基本性质,插入节点)》

如果没有第三条性质的约束,这就是一棵红黑树,但是如果我们将第3条性质的约束画出来就会发现它不是一棵红黑树,如下图所示:

《红黑树之一(基本性质,插入节点)》

根据第三条性质的要求,从50到75的左叶子所经过的黑节点数目和从50到80的任意叶子所经过的黑节点数目应该一样多,显然不是,这就是第三条性质的价值。事实上观察这棵树可以发现,如果这棵树是红黑树的话,红黑树的状态就会很差,两个交叉在根节点的链表就成了所谓的红黑树。

红黑树的插入、删除、查询操作的算法复杂度也是O(logn),另外与AVL树相比,红黑树有更好的统计性能,因此相对而言,它更常用。

二、红黑树的查询

红黑树本质上还是一颗二叉树,因而其查询和AVL树完全相同,没什么特别之处。

三、红黑树的插入

红黑树的插入需要注意的是,插入时,新节点的颜色都是红色的,这是因为红黑树要求其任意一个节点到以该节点为根节点的子树上的所有叶子节点的路径上的黑节点数目相同,因而如果添加的新节点的默认颜色为黑色,则每次该性质都会被破坏。因而添加新节点时,新节点的颜色都为红色。

插入可以分两步来完成:第一步将新的红色节点插入,第二步分析判断属于哪一种情形,并进行调整处理。调整需要分以下情形来分别处理:

3.1 新节点不存在父节点

这种情形处理很简单,只要将新节点的颜色修改为黑色即可,该节点实际上就是红黑树的根节点。

3.2 新节点的父节点的颜色为黑色

如果父节点的颜色为黑色,则无需做任何调整。

3.3 新节点的父节点和叔父节点均为红色

《红黑树之一(基本性质,插入节点)》

上图往原来的红黑树中添加了新的节点N(ew),由于其父节点P(arent)和叔U(ncle)节点都是红色的,因而需要进行调整,调整的方法是:

  1. 将其父节点P和叔父节点U的颜色变为黑色
  2. 新节点N颜色不变
  3. 其祖父节点G(randpa)(节点50)颜色改为红色

这一步调整完后,可以得到

《红黑树之一(基本性质,插入节点)》

但是此时插入并没有完成,由于新节点的祖父节点的颜色改变了,因而我们还需要判断这个改变是否会违背红黑树的限制,如果会就需要根据具体的情形继续进行调整,这个过程要一直递归的进行直到确保红黑树的限制都被满足。(此时假设G就是根节点,则它满足情形一,即不存在父节点的情形,直接将其颜色修改为黑色即可)。简单的说就是如果某个节点的颜色在调整过程中被变成了红色,就要将它看做新节点,来进行分析判断并进行调整处理。

需要注意的是识别这种情形的依据是:新节点的父节点为红色,并且新节点的叔父节点的颜色也为红色,对新节点是其父节点的左子树还是右子树以及父节点和叔父节点的相对位置是没有要求的。

3.4 新节点的父节点是红色,叔父节点是黑色或不存在,新节点是其父节点的左孩子,父节点是祖父节点的左孩子

《红黑树之一(基本性质,插入节点)》

上图往原来的额红黑树中添加了新节点N由于其父节点P(arent)和叔U(ncle)节点都是红色的,因而需要进行调整,调整的方法是:

首选对以新节点的祖父节点G为根的子树进行一次右旋,可以得到

《红黑树之一(基本性质,插入节点)》

然后再将节点P和G的颜色互换,得到

《红黑树之一(基本性质,插入节点)》

显然N,P,G,U的颜色已经满足红黑树的要求,再考察这个调整对路径上黑节点数目的影响:

  • 调整前,节点N到根节点的路径上需要经过黑节点G,调整之后需要经过黑节点P,黑节点数目不变。
  • 调整前,节点P到根节点的路径上需要经过黑节点G,调整之后需要经过黑节点P,黑节点数目不变。
  • 调整前,节点G到根节点的路径上需要经过黑节点G,调整之后需要经过黑节点P,黑节点数目不变。
  • 调整前,节点U到根节点的路径上需要经过黑节点U,G,调整之后需要经过黑节点U,P,黑节点数目不变。

因而完成这两步调整后,插入即可结束

3.5 新节点的父节点是红色,叔父节点是黑色或不存在,并且新节点是其父节点的右孩子,父节点是祖父节点的左孩子

《红黑树之一(基本性质,插入节点)》

上图往原来的额红黑树中添加了新节点N由于其父节点P(arent)和叔U(ncle)节点都是红色的,因而需要进行调整,调整的方法是:

首选对以新节点的父节点P为根的子树进行一次左旋,可以得到

《红黑树之一(基本性质,插入节点)》

调整后得到的情形和情形4相同,按照情形进行处理即可(即做一次右旋,然后交换颜色),也就说说在这种情形下需要先做一次左旋,再做一次右旋。

情形4和情形5讨论的是父节点是祖父节点的左孩子的情形,父节点是祖父节点的右孩子的情形和分析的情形对称。

    原文作者:算法小白
    原文地址: https://blog.csdn.net/goodluckwhh/article/details/11804733
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞