红黑树简介及左旋、右旋、变色

article/2025/9/29 5:29:10

红黑树简介及左旋、右旋、变色

红黑树(Red Black Tree)是一种自平衡二叉搜索树(二叉查找树),是一种特殊的二叉搜索树,在进行插入和删除时通过特定操作保持二叉树自身的平衡,从而获得较高的查找性能。

红黑树的平衡操作通过左旋、右旋和变色来实现,平衡的过程是比较复杂的,但通过平衡操作,可以获得更高效的性能。对二叉搜索树进行平衡后,最坏情况的运行时间得到优化,可以在O(logN)的时间复杂度内完成查找、插入和删除,N是二叉搜索树中的节点数。

一、二叉搜索树的性能分析

红黑树是一种特殊的二叉搜索树,所以本文先从二叉搜索树说起。

二叉搜索树是一种特殊的二叉树,具有如下特性:

1. 如果二叉树的左子树不为空,则左子树上所有节点的值均小于它的根节点的值。

2. 如果二叉树的右子树不为空,则右子树上所有节点的值均大于它的根节点的值。

3. 如果独立地看,左子树、右子树也分别为二叉搜索树。

二叉搜索树的实现,可以参考:Python实现二叉搜索树_小斌哥ge的博客-CSDN博客

向二叉搜索树中插入数据时,为了满足二叉搜索树的特性,会递归地比较插入节点的值与根节点的值,将数据插入正确的位置。

如在一棵空二叉搜索树中插入 [50, 77, 55, 29, 10, 30, 66, 80, 51, 18, 90] ,得到的二叉搜索树结构如下图:

从结构图可以看出,这棵二叉搜索树是平衡的,当在二叉搜索树中查找数据时,按照二分法查找的思想,从根节点开始,然后到子树中进行查找,如果没有查找到目标数据,每次都会往树的下一层进行查找,需要的最大查找次数等于树的深度。最坏的情况就是找到树的最深一层,所以在这棵树中查找的最坏情况是查找4次。

还是上面例子中的数据,假设比根节点50大的数据是升序排列的,如 [50, 51, 55, 66, 77, 80, 90, 29, 10, 30, 18] ,比根节点50小的数据顺序不变,将这些数据插入到二叉搜索树中,得到的二叉搜索树结构如下图:

很明显,这棵二叉搜索树是不平衡的。在这棵树中查找数据的最坏情况需要查找7次,查找次数多的原因就是树的不平衡,右子树一直在往深度上延伸。如果把根节点和右子树拿出来,结构如下图:

根据结构图,这是一棵右斜树。它虽然是一棵二叉树,但它更像是一个链表,正在向链表“退化”。链表的时间复杂度是O(N),平衡二叉树的时间复杂度是O(logN),当N很大的时候,O(N)与O(logN)的性能差距是很大的。

可见,二叉搜索树的插入顺序会影响到树的结构,从而影响性能。对于上面的例子,总共只有11个节点,出现7个数据顺序排列的可能性不大,但在实际的应用场景中,节点可能是110个,11000个,11000000个,甚至更多。在数据量增大的时候,这些数据中出现一段或多段数据顺序排列的可能性是很大的,这就会造成二叉搜索树极度不平衡,向链表退化,性能大大降低。

所以,保持二叉搜索树的平衡,对性能的保证有至关重要的作用。由于数据是动态变化的,会动态地增加或减少,不可能在构造二叉搜索树前控制数据的排列顺序。要保持二叉搜索树的平衡,就要在每增加一个节点或每减少一个节点时都保持平衡,即让二叉搜索树一直保持平衡,这样二叉搜索树的性能就不可能向链表退化。

当二叉搜索树中的节点数量发生改变时,使用一些策略来保持平衡,红黑树就是这样一种二叉树。

二、红黑树简介

红黑树是一种自平衡二叉搜索树,每个节点都有颜色,颜色为红色或黑色,红黑树由此得名。除了满足二叉搜索树的特性以外,红黑树还具有如下特性:

1. 节点是红色或黑色。

2. 根节点是黑色。

3. 所有叶子节点都是黑色的空节点。(叶子节点是NIL节点或NULL节点)

4. 每个红色节点的两个子节点都是黑色节点。(从每个叶子节点到根的所有路径上不能有两个连续的红色节点)

5. 从任一节点到其每个叶子节点的所有路径都包含相同数目的黑色节点。

要知道什么是红黑树,必须记住这5条特性。这5条特性其实是5条规定,只有满足这5条规定才属于红黑树。对于二叉搜索树的特性,只要理解了,很容易记住,但对于红黑树的5条特性,需要“死记硬背”。

如上面例子中的二叉搜索树,可以加上颜色变成一颗红黑树。(实际的红黑树是一个节点一个节点插入的,如下的构造过程只是为了先理解红黑树的5条特性)

1. 先加上叶子节点,并把所有节点都标记为黑色。

2. 这棵二叉树显然不满足红黑树的特性5,如节点10到左子树的叶子节点的路径上有一个黑节点,到右子树的叶子节点的路径上有两个黑节点,所以要将一些黑节点变成红节点。

从根节点50开始,使根节点到每个叶子节点的路径上都有4个黑节点,得到的红黑树如下。

当然,也可以使根节点到每个叶子节点的路径上都有3个黑节点,得到的红黑树如下。

现在看一下这两棵树是否满足红黑树的5条特性,可以一条一条的对比,至于构造的过程先不管(这其实是硬拼出来的),后面再讲怎么构造。

根据红黑树的特性5,任意节点到其所有叶节点的路径上的黑节点数都相同,从而保持红黑树的平衡。如果只看黑节点,这种平衡是完美的平衡,所以红黑树的平衡也称为黑色完美平衡。当然,因为红节点的存在,红黑树并不是完美平衡的,甚至有可能不满足平衡二叉树的特性。

当在红黑树中插入节点或删除节点时,红黑树的平衡很可能会被破坏(不满足其中一条或多条特性),要立即对红黑树进行调整,使红黑树重新满足5条特性。

调整平衡的操作包含左旋、右旋和变色,下面依次对这些操作进行介绍。

三、红黑树的左旋和右旋操作

对于一棵红黑树,它满足红黑树的5条特性。插入或删除节点之后,红黑树就发生了变化,很可能不再完全满足红黑树的5条特性了,也就是不再是一棵红黑树了,而是一棵普通的二叉搜索树。这时候,为了使二叉搜索树重新变成红黑树,就需要对二叉搜索树进行操作,使它满足红黑树的5条特性。

通过旋转,可以使二叉搜索树重新满足红黑树的5条特性。旋转分为左旋和右旋。

1. 红黑树的左旋

左旋:以某个节点作为支点(旋转节点),其右子节点变为旋转节点的父节点,右子节点的左子节点变为旋转节点的右子节点,旋转节点的左子节点保持不变。右子节点的左子节点相当于从右子节点上“断开”,重新连接到旋转节点上。

为了不失一般性,可以看下图中的例子。左边是左旋前的红黑树局部结构,先不考虑整体,只看局部,左旋前不满足红黑树的特性5。

左旋时,旋转节点为节点50,左旋后,旋转节点的右子节点70变为旋转节点50的父节点,右子节点的左子节点60从右子节点70上“断开”,成为旋转节点50的右子节点。

左旋后,结构如右图,这个局部重新满足了红黑树的特性5,达到目的。

再看另一个左旋的例子,左边是左旋前的局部结构,以节点10作为旋转节点,左旋后,旋转节点的右子节点20成为旋转节点10的父节点,右子节点的左子节点(这里是一个叶子节点NIL)从右子节点上“断开”,成为旋转节点10的右子节点。

2. 红黑树的右旋

右旋:以某个节点作为支点(旋转节点),其左子节点变为旋转节点的父节点,左子节点的右子节点变为旋转节点的左子节点,旋转节点的右子节点保持不变。左子节点的右子节点相当于从左子节点上“断开”,重新连接到旋转节点上。

不难看出,左旋和右旋是相反的,可逆的。

下图中的例子仍然是红黑树的局部,左边的结构不满足红黑树的特性5。

右旋时,旋转节点为节点70,右旋后,旋转节点的左子节点50变为旋转节点70的父节点,左子节点的右子节点60从左子节点50上“断开”,成为旋转节点70的左子节点。右旋后(右图),重新满足了红黑树的特性5。

同样再看一个右旋的例子,左边是右旋前的局部结构,以节点30作为旋转节点,右旋后,旋转节点的左子节点20成为旋转节点30的父节点,左子节点的右子节点(这里是一个叶子节点NIL)从左子节点上“断开”,成为旋转节点30的左子节点。

通过对左旋和右旋的介绍和举例,左旋和右旋的目的都是通过旋转节点的方式使二叉搜索树重新满足红黑树的特性,左旋和右旋是互逆的,根据不同的情况使用不同的旋转方式。

四、红黑树的变色操作

当对红黑树进行插入或删除节点之后,如果不再完全满足红黑树的5条特性,除了旋转,变色也可以使二叉搜索树重新满足红黑树的5条特性。

变色:将节点的颜色由红变黑或由黑变红。

向红黑树中插入节点时,新节点的颜色都设置为红色。不管新节点是什么颜色,特性3都不可能被破坏,特性1、2、4都有可能被破坏。如果插入的节点是黑色,则一定会破坏特性5,需要进行调整,如果插入的节点是红色,则一定不会破坏特性5。所以将新节点设置为红色,可以降低破坏红黑树特性的可能性。

1. 添加节点

如下的左图是红黑树的一个局部,一开始是满足红黑树的特性的,在其中插入了红色节点10,两个红节点连在一起了,不再满足红黑树的特性4。

通过变色,先将节点20变成黑色,特性4满足了,但又不满足特性5,所以继续将节点30变成红色,节点40变成黑色。

经过3次变色后,从局部看,已经重新满足了红黑树的特性。但是,从整棵树来看,还不一定满足红黑树的特性,如果节点30的父节点也是红色,则还需要继续对这棵树进行调整(上面的左旋和右旋例子中也有这种情况)。

2. 删除节点

如下的左图是红黑树的一个局部,一开始是满足红黑树的特性的,将节点90删除后,不再满足红黑树的特性5。

通过变色,先将节点80变成黑色,但仍不满足特性5,继续将节点70变成红色,重新满足了红黑树的特性。

经过两次变色,重新满足了红黑树的特性,对于这个例子,只要局部满足了,整棵树一定是满足红黑树的。

五、红黑树的旋转和变色综合案例

上文中介绍旋转和变色时,是独立对它们进行分析的。这两种调整方法都可以使被破坏规则的红黑树重新满足红黑树的特性,更多的时候,需要灵活地配合使用,使调整更高效。

下面来看一个简单的例子。使用文章开头的红黑树,结构如下图。

1. 在红黑树中插入节点20,插入后不满足红黑树的特性4。

2. 将节点18从红色变成黑色,变色后不满足红黑树的特性5。

3. 以节点10作为旋转节点,进行左旋,左旋后还是不满红黑树的特性5。

4. 将节点10从黑色变成红色,变色后,重新满足了红黑树的5条特性。

经过变色,左旋,变色,三个步骤之后,插入节点后的树重新成为一棵红黑树。

本文中举例的结构图是为了方便理解红黑树以及红黑树的旋转和变色,一棵真正的红黑树是一个节点一个节点地插入而得到的,并一定能得到上面图形里的这些结构。对于红黑树的插入、删除和代码实现,本专栏的其他文章会继续介绍。


http://chatgpt.dhexx.cn/article/QtXaAPUk.shtml

相关文章

字符串的左旋右旋问题(C语言实现,三种方法求解)

字符串左旋右旋问题其实是同理的,下边以左旋为例: 方法一 思路:左旋一次就是将整个字符串向左移一个字符,第一个字符(arr[0])移动到最右侧。这样循环操作左旋次数就是最终左旋结果,如上图所示。…

二叉树的左旋与右旋

对于在一颗结点和层数比较多的二叉树上查找一个元素时, 二叉排序树的查找效率远远高于一颗普通的树。 如下为普通二叉树和二叉排序树: 假设查找结点20 /*** 二叉树结点*/ public class TreeNode {public int val;public TreeNode left;public TreeNode…

二叉树旋转--左旋|右旋

二叉树旋转 二叉树的旋转主要是应用在AVL树中,当添加一个节点时候导致左右两个子树的高度差不在是-1 , 1 , 0而变成了2 或者-2。此时就需要用到左旋/右旋了。当然左右旋或者有左旋也是基于左旋和右旋的就是顺序不同,理清旋转的顺…

算法-红黑树的左旋右旋

1、左旋 private void leftRotate(RBTreeNode node) {RBTreeNode right node.right;RBTreeNode parent node.parent;if (parent null) {root right;right.parent (null);} else {if (parent.left ! null && parent.left node) {parent.left (right);} else {par…

平衡二叉搜索树 - 左旋|右旋

上一节 红黑树前奏 - 对树的基本理解 我们讲到 二叉搜索树 单向链表的问题&#xff0c;为了解决这个问题&#xff0c;我们引入了平衡二叉搜索树。 所谓平衡二叉搜索树&#xff0c;必须满足 BST 的特性。何为平衡&#xff0c;每个节点的平衡因子的绝对值 < 1. 那么平衡因子…

HashMap 数据结构之红黑树, 红黑树在什么时候左旋 右旋 如何旋转

树结构是数据结构中最经典最常用的结构之一&#xff0c;也是面试中常问的面试题&#xff0c;最近学习了一下红黑树的知识&#xff0c;记录整理一下 文章目录 一、红黑树的特征二、变色左旋和右旋 1.变色规则2.左旋3.右旋总结 前言 面试中我们经常会被问到 HashMap 在 1.7 和 1.…

java平衡二叉树左旋,Java 平衡二叉树之单旋(左旋,右旋)与双旋

1.平衡二叉树 平衡二叉树也叫平衡二叉搜索树(Self-balancing binary search tree)又被称为AVL树&#xff0c; 可以保证查询效率较高。 具有以下特点&#xff1a;它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1&#xff0c;并且左右两个子树都是一棵平衡二叉树。 首先…

平衡二叉树的左旋和右旋

文章目录 复习树1. 树的概念2. 二叉树(Binary Tree)3. 满二叉树4. 完全二叉树5. 二叉堆6. 二叉搜索树 左旋和右旋7. 平衡二叉树(平衡二叉搜索树) 本文章是我的库存文章&#xff0c;本来不发的&#xff0c;但还是发吧&#xff0c;请跳到第7节&#xff0c;那才是讲左旋和右旋的。…

HashMap-红黑树插入平衡、左旋、右旋源码解析

目录 一、树的演变 二、红黑树 1.红黑树的特点 2.树左旋右旋的过程 3.红黑树插入节点情景分析&#xff1a; 三、HashMap插入平衡、左旋、右旋源码解析 1.添加值 2.插入平衡 3.左旋、右旋 一、树的演变 为什么会有树&#xff0c;因为链表的查询效率是logOn,树的查询效率…

HashMap底层实现原理:红黑树左旋右旋

HashMap中的红黑树左旋、右旋&#xff1a; 一、什么是左旋、右旋&#xff1a; 红黑树的性质&#xff1a; 每个节点要么是黑色&#xff0c;要么是红色根节点是黑色每个叶子节点&#xff08;NIL&#xff09;是黑色每个红色结点的两个子结点一定都是黑色任意一结点到每个叶子结点…

平衡二叉查找树(AVL)的构建——左旋右旋

原文链接&#xff1a;https://www.cnblogs.com/ZhaoxiCheung/p/6012783.html 平衡二叉树&#xff0c;又称AVL&#xff08;Adelson-Velskii和Landis&#xff09;树&#xff0c;是带有平衡条件的二叉查找树。这个平衡条件必须要容易保持&#xff0c;而且它必须保证树的深度是 O&…

详解红黑树之左旋右旋

为什么要左旋右旋&#xff1f; 为了使得左右子树的高度差在一定范围内&#xff0c;需要通过旋转调整&#xff0c;这样就可以保持平稳的搜索效率 左旋&#xff1a; 步骤 1.设原来E的父节点是father&#xff0c;那么左旋之后需要改变的是&#xff1a; 2.S和father的关系&#…

avl树左旋右旋的理解

一直没搞懂非平衡二叉树变平衡二叉树时左旋右旋&#xff0c;今天下定决心搞懂&#xff0c;然后在众多博客中终于找到了这样一篇&#xff0c;非常形象&#xff0c;记录如下&#xff1a; AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一&…

搞懂平衡二叉树的左旋右旋双旋(Java实现)

刚看到韩顺平老师的数据结构与算法对于平衡二叉树的讲解&#xff08;最后会附上地址&#xff09;&#xff0c;有如下理解&#xff0c;希望能帮助大家&#xff01;哪里需要改正的欢迎指正&#xff01; 平衡二叉树&#xff1a;一种二叉排序树&#xff08;BST Binary Sort Tree&a…

图示讲解AVL平衡二叉树的左旋和右旋

AVLTree 高度平衡的搜索二叉树 一棵平衡树&#xff0c;或是空树&#xff0c;或是具有以下性质的二叉搜索树&#xff1a;左子树和右子树都是AVL树&#xff0c;且左右子树的高度之差的绝对值不超过1。 该二叉树&#xff0c;根结点的右子树高度为3&#xff0c;左子树高度为2。…

左右旋对比

目录 前言 一&#xff0c;逆置法 1.1逆置思路 1.2逆置实现 二&#xff0c;左旋和右旋对比 右旋代码分析 特点对比 前言 之前在up主的博客里面已经有过了对于左旋的三种实现方法。当然&#xff0c;如果我们考虑到时间复杂度的问题&#xff0c;那么我们只要一种方法&#xf…

平衡二叉树的左旋右旋详解 看不懂你打我

平衡二叉树的左旋右旋 看不懂你打我 左旋右旋的操作为什么要左旋右旋左旋右旋能保持排序二叉排序树的性质吗下次写平衡二叉树的LL、RR、LR、RL。 左旋右旋的操作 1.左旋&#xff1a;对X节点左旋&#xff0c;即以X的右孩子Y为轴&#xff0c;将X节点转下来&#xff0c;变为Y的左…

二叉树的旋转,左旋和右旋

在AVLTree中经常会有以某个节点为点对子树进行旋转的操作&#xff0c;今天就和大家分享一下什么是二叉树的旋转。 这是一棵二叉树&#xff0c;上图称为图一。 将图一中的树以1为旋转点进行左旋后得到图二&#xff1a; 将图一中的树以1为旋转点进行右旋旋后得到图三&#xff1…

day062:平衡二叉树——左旋、右旋

二叉树、平衡二叉树的介绍&#xff1a;day061&#xff1a;二叉树、二叉查找树、平衡二叉树_ZQyyds&#xff1a;&#xff09;的博客-CSDN博客 目录 一、平衡二叉树的左旋 1.为什么要左旋、右旋&#xff1f; 2.什么是左旋&#xff1f; 3.图解 二、平衡二叉树的右旋 1.什么是…

大型json文件格式化【超简单】

问题 遇到了一个很大的JSON文件&#xff08;约4M&#xff09;&#xff0c;想格式化查看&#xff0c;在线json工具会直接崩溃&#xff0c;网上其他同学说的python方法之类的我也都实验失败&#xff0c;但是发现了vs code中一个超强的代码格式化 解决1&#xff08;2019.2.10更…