当前位置: 首页 > 科技观察

看了这么多红黑树文章,你明白了吗?_0

时间:2023-03-18 15:07:53 科技观察

很早以前就想写一篇关于红黑树的文章,但是因为担心自己没有看透,所以一直不敢写。于是在重新阅读了很多文章和资料后,决定彻底了解红黑树。也希望你能在面试中取得好成绩。好了废话不多说,开始今天的文章。整篇文章的思路是这样的。红黑树其实就是一种数据结构。它是为高效的增删改查而设计的,所以我们文章的排序也会按照这个思路来进行。我们先把二叉搜索树逐步介绍到红黑树中,然后再详细讲解。如果看过其他文章,肯定知道红黑树比较麻烦。希望大家在分析之前耐心的仔细理解每一张图。1.二叉搜索树在正式开始了解红黑树之前,我们先了解一下二叉搜索树的概念,由浅入深,希望大家不要着急,下面是二分搜索树:从这里图中,我们会发现以下规则:(1)左子树上所有节点的值都小于等于其根节点的值。(2)右子树上所有节点的值都大于等于其根节点的值。如果我们要找到一个数字11,这个过程是怎样的?上面的过程已经很清楚了。查找时,先与根节点比较。如果大于根节点,则从右子树开始查找。如果小于根节点则从左子树开始查找,然后重复上面的过程,直到找到我们需要的元素。这个过程是一个搜索操作。添加和删??除呢?其实原理是一样的。我们第一步就是找到我们需要插入的位置,然后插入元素。这样看二叉查找树不是很好吗?别着急,让我们继续看看这个情况。如果我们一开始还是用9作为根节点,那么依次插入13、15、17、19。且看怎么回事:一棵好树变成了这个鬼样子,变得“一面倒”了。这个时候找19怎么样?这样效率太低了,完全失去了二叉搜索树的优势。我们应该做什么?由于上面的二叉搜索树在插入的时候变成了“一条腿”,也就是失去了平衡,所以我们稍微改进一下,使用平衡二叉树。2.平衡二叉树下面是一棵平衡二叉树。上面的二叉树是平衡二叉树,也称为AVL树。仔细分析后会发现以下特点:(1)从任意节点开始,左右子树深度差的绝对值不超过1。(2)左右子树仍然是平衡的二叉树。现在我们插入一个元素4,这时候会发生什么呢?我们从图中可以看出,插入4后平衡被打破了,怎么办?既然平衡被打破了,我们就应该想办法纠正它。我们发现经过调整后,我们的二叉树又恢复了平衡。对于其他的插入情况,大家可以私下试一试,最终会得出一个结论,平衡二叉树在插入时最多只需要旋转两次就可以恢复平衡。从上面的过程中,我们会发现平衡二叉树真的很好。它不仅在查找时具有二叉搜索树的优点,而且在插入时可以通过调整继续维护。那么为什么要使用红黑树呢?我觉得可以从以下两个方面来考虑:(1)删除:对于一棵平衡二叉树,在最坏的情况下,需要维护被删除节点到根节点的路径上所有节点的平衡路径,旋转的顺序是O(logN)。但是红黑树不一样。最多只需要旋转3次就可以重新平衡,旋转的顺序是O(1)。(2)保持平衡:平衡二叉树的高度是平衡的,也就是说在大量插入和删除节点的场景下,需要更频繁地调整平衡二叉树来保持平衡。注意:在大量查找的情况下,平衡二叉树效率更高,也是首选。在大量增删改查的情况下,红黑树是首选。鉴于以上原因,我们采用了更好的红黑树结构。红黑树上面说了这么多次,相信你已经迫不及待想要了解它了。下面正式拉开红黑树的序幕。3.红黑树红黑树听名字就知道了,它涉及两种颜色:红色和黑色。我们直接看一下:上图是一棵红黑树,你会发现它有如下特征(下面的特征最好看一个特征再看红黑树):(1)每个节点只有两种颜色:红色和黑色。(2)根节点为黑色。(3)每个叶子节点(NIL)都是一个黑色的空节点。(4)从根节点到叶子节点,不会有连续的两个红色节点。(5)从任意一个节点到叶子节点,这条路径上有相同数量的黑色节点。这五个就是红黑树的特征。每次看一个特征最好再看一遍图片,这样可以加深理解。这五个特征看起来确实很复杂,但也正是因为有这些复杂的特征,才保证了红黑树的优良特性。如何保证?下面从增删改查四个角度一一分析:1.查询节点查询节点是最简单的一个。它的搜索过程与二叉搜索树的搜索过程相同。如果查找元素大于当前节点,则从右子树继续查找比较,如果查找元素小于当前节点,则从左子树继续查找比较。将不详细描述搜索过程。2.插入节点插入节点是最麻烦的,分为三种情况。一个一个来看,哪个更有条理。第一种情况:新节点没有父节点也没有父节点。只有一种情况,就是插入的节点是整棵树的第一个节点,也就是根节点。为此,我们只需要将插入的节点涂成黑色就OK了。.这也保证了属性2:根节点是黑色的。第二种情况:新节点的父节点为黑色。让我们举个例子。比如上面的红黑树,我们插入节点14,我们看看会发生什么?在这种情况下,我们发现新插入的节点14的父节点是黑色的。现在为了确保红黑树的属性,我们针对每一个属性进行检查。只要有一个不满意,我们都需要调整。重新检查后,我们会发现每一项都符合要求。此时无需调整。第三种情况:新节点的父节点为红色。让我们举个例子。比如我们在原来的红黑树的基础上插入节点21,这时候会发生什么?这时候,还是老规矩。一一看红黑树的五个特性,只要违反其中一个,就需要进行调整。我们来看一下:(1)每个节点只有两种颜色:红色和黑色。这个很满意(2)根节点为黑色。这个也很满意。(3)每个叶子节点(NIL)都是一个黑色的空节点。这个很满意(4)从根节点到叶子节点,不会有连续的两个红色节点。发现这篇文章并不令人满意。不满足上面的规则,那么这个时候需要调整吗?如何调整问题?因为无法直接查看父节点,所以我们需要观察另一个节点,即新节点的叔节点。根据叔叔节点的颜色进行调整。有两种调整方式:颜色变化和旋转。(1)叔叔节点是红色的:此时插入的节点是21,但是叔叔节点是27,最好是红色的。直接看调整步骤:第一步:将新节点21的父节点改为黑色。这个时候再检查一下红黑树的5个特性是否满足。一个接一个,第五个不满足,即从任意一个节点开始到叶子节点,这条路径上的黑节点个数不一样。比如从25开始,这个时候怎么办?然后继续调整。第二步:将22的父节点25变成红色。这仍然是一个古老的规则。不要嫌麻烦,因为只有一步步走过烦恼,才能牢记五戒的特点。经过比较,我们会发现节点25和节点27是两个连续的红色节点,再次违反了规则4。我应该怎么办?然后继续调整就OK了。这个时候还需要继续向上调整吗?如果你这样做,你就错了,因为不断向上调整最终会使根节点变成红色,你就会进入死胡同。我们下去吧。第3步:将节点27变为黑色来吧,继续并重新检查这5个规则特征。很明显节点17和节点25是两个连续的红色,又被打断了。是不是太累了,调整了这么久,还是没有保证5条规则,感觉还不如平衡二叉树呢。如果你现在有这种感觉,我只能说,希望你继续坚持下去,胜利指日可待。第四步:将节点17和节点18变成黑色节点,现在可以对比5条规则,看是否完全保证。写到这里真的很累,看这篇文章的感觉也是一样的,不过这种情况只是插入情况中的一种。继续往下看:(1)叔节点为黑:这种情况有两种情况:第一种情况:新插入的节点是父节点的左孩子;第二种情况:新插入的节点是父节点右孩子沿袭了第一遍的思路,我们对这两种情况进行同样的操作,最终可以保证红黑树的五个特性。至此,插入操作的所有情况都说明了。另外,关于左手和右手的知识我这里就不解释了,因为红黑树的层次你已经看过了,相信平衡二叉树你一定看过。将介绍左撇子和右撇子的情况。3.节点的删除红黑树的删除说实话比较复杂。如果看过算法介绍,应该能看懂。我们也将在这里进行一般性的解释。删除大致可以分为三种情况。(1)第一种情况:待删除节点有零个子节点。这种情况最简单,就是删除根节点或叶子节点(这里是Non-NULLleafnodes),直接删除根节点即可。如果叶子节点是红色的,也可以直接删除。如果叶子节点是黑色的,那么就需要调整。调整步骤与插入时相同。(2)第二种情况:待删除节点此时有子节点。将子节点的值替换为要删除的节点的值。现在我们的5替换11之后,我们又回到了第一种情况。如果节点5是红色的,可以直接删除。如果节点5为黑色,则需要进行调整。此时节点5为叶节点。调整步骤与插入相同。(3)第三种情况:待删除的节点有两个子节点,现在删除的节点有两个子节点。同样,我们可以进行第二种情况的操作。如果节点13之前是叶子节点,那么就和第一个的情况一样,如果节点13是红色的,可以直接删除,如果节点13是黑色的,那么需要调整,并且节点此时的13是叶子节点。调整步骤与插入相同。如果节点13之前还有子节点,则同第二种情况。然后继续替换判断。以上是删除的情况,最后一种情况是修改。本例是查找和插入相结合,即先找到要修改的元素,修改完值再继续调整。现在还有最后一个问题。据说红黑树很重要。它为什么如此重要?我们来看看使用场景。4、红黑树的应用真的太多了,比如java中的HashMap、TreeMap。还有就是经常用到linux。这种数据结构是面试时经常被问到的问题,希望大家能够理解理解。java中如何手撕红黑树,我会在后续的文章中补充。如有问题,请批评指正。