红黑树-旋转

此篇博客我们讨论红黑树的旋转(左旋和右旋),为了更好的理解旋转,我们只关注红黑树中关于二叉查找树部分的规则,而不关注红黑树中关于本身红黑树定义部分的规则。

  • 二叉查找树规则
    • 规则一:若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    • 规则二:若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    • 规则三:左、右子树也分别为二叉查找树;
左旋

现有红黑树结构如下:

这里写图片描述

为了更好的理解,我们给节点X、Y、A、B和C一个值,并把要进行左旋的节点X标为红色(注意:和红黑树的红色没关系,仅仅起一个提示的作用);

这里写图片描述

我们再接着分析,此时我们需要对节点X进行左旋操作,这就意味着要以节点X为轴心,然后把节点X的右子树Y往左旋转,也就是一个上浮,结果如下:

这里写图片描述

此时左旋完毕,但是树形结构已经不符合二叉树的结构标准了,所以我们还要进行进行一步处理,也就是节点B该往哪放的问题?我们可以先试一下,如下:

这里写图片描述

这么放有问题吗?

很显然这里违背了二叉查找树的规则,尽管节点B比节点C的值要小,看似作为节点C的左子节点是正确的,但是不要忘了未旋转前,节点B是节点Y的左子节点,所以节点B的值比节点Y的值也要小,因此节点B压根就不能放在节点Y的右子树,那我们再换一种放法,如下:

这里写图片描述

现在我们再看一下,发现问题已经完美解决!

右旋

现有红黑树结构如下:

这里写图片描述

为了更好的理解,我们给节点X、Y、A、B和C一个值,并把要进行右旋的节点X标为红色(注意:和红黑树的红色没关系,仅仅起一个提示作用);

这里写图片描述

我们再接着分析,此时我们需要对节点X进行右旋操作,这就意味着要以节点X为轴心,然后把节点X的左子树Y往右旋转,也就是一个上浮,结果如下:

这里写图片描述

此时右旋完毕,但是树形结构已经不符合二叉树的结构标准了,所以我们还要进行进行一步处理,也就是节点C该往哪放的问题?我们可以先试一下,如下:

这里写图片描述

这么放有问题吗?

很显然这里违背了二叉查找树的规则,尽管节点C比节点B的值要大,看似作为节点B的右子节点是正确的,但是不要忘了未旋转前,节点C是节点Y的右子节点,所以节点C的值比节点Y的值也要大,因此节点C压根就不能放在节点Y的左子树,那我们再换一种放法,如下:

这里写图片描述

现在我们再看一下,发现问题已经完美解决!

总结
  1. 旋转时只需要关注二叉查找树部分的规则即可;
  2. 左/右旋就是以旋转的节点为轴心,把它的右/左子树进行上浮;
  3. 上浮之后对于中间多余的节点按照二叉查找树的规则重新放即可;
  4. 不需要死记硬背,需要旋转时自己画一画就出来了;
<think>嗯,用户想了解红黑树的左旋和右旋的实现原理,数据结构以及算法相关的知识。我需要根据提供的引用资料来整理答案。首先,红黑树是一种自平衡的二叉查找树,通过左旋和右旋来维持平衡。左旋和右旋是调整树结构的基本操作,用来修复插入或删除节点后可能破坏的红黑树性质。 根据引用[1],红黑树在增删改操作后可能需要通过变色、左旋、右旋来维持性质。左旋和右旋主要处理父子节点的位置调整。引用[3]提到红黑树不是高度平衡的,但通过红黑规则来保持平衡,添加节点时需要遵循特定规则,可能需要进行旋转操作。引用[4]和[5]也提到红黑树的结构特性以及旋转操作的重要性。 左旋的具体步骤:假设以节点x为支点,其右子节点y变为x的父节点,y的左子节点β成为x的右子节点。这样左旋后,x下移到左子树,y上升。右旋则是相反操作,以节点y为支点,其左子节点x变为y的父节点,x的右子节点β成为y的左子节点。 需要注意旋转后节点间的连接关系,包括父节点、子节点的更新,以及颜色的调整。例如,在HashMap的源码中,左旋和右旋操作会调整指针指向,确保树的结构正确,同时可能需要变色来满足红黑规则。 用户可能的问题可能涉及旋转的具体步骤、为什么需要旋转旋转如何保持平衡等。需要结合引用中的信息,用中文清晰解释,并确保LaTeX公式正确,行内公式用$...$,独立公式用$$...$$。</think>### 红黑树的左旋与右旋实现原理 红黑树通过**左旋**和**右旋**调整树结构,以维持以下红黑规则: 1. 根节点为黑色; 2. 红色节点的子节点必须为黑色; 3. 从任意节点到其所有叶节点的路径包含相同数量的黑色节点[^3]。 --- #### **左旋(Left Rotation)** **目的**:降低右子树高度,调整父子节点位置。 **操作步骤**(以节点$x$为支点): 1. 设$x$的右子节点为$y$,$y$的左子节点为$β$; 2. 将$β$设为$x$的右子节点; 3. 将$y$的父节点设为$x$的父节点; 4. 将$x$设为$y$的左子节点; 5. 更新父节点的子节点引用(若$x$是根节点,更新根为$y$)。 **图示**: $$ \begin{array}{c} \text{旋转前} & \quad & \text{旋转后} \\ x & \quad & y \\ \uparrow & \quad & \uparrow \\ y & \quad & x \rightarrow β \\ \downarrow & \quad & \downarrow \\ β & \quad & \\ \end{array} $$ **源码示例**(参考HashMap实现[^1]): ```java // 左旋操作核心逻辑 void rotateLeft(Node x) { Node y = x.right; x.right = y.left; // 步骤2 if (y.left != null) y.left.parent = x; y.parent = x.parent; // 步骤3 if (x.parent == null) root = y; // 步骤5 else if (x == x.parent.left) x.parent.left = y; else x.parent.right = y; y.left = x; // 步骤4 x.parent = y; } ``` --- #### **右旋(Right Rotation)** **目的**:降低左子树高度,调整父子节点位置。 **操作步骤**(以节点$y$为支点): 1. 设$y$的左子节点为$x$,$x$的右子节点为$β$; 2. 将$β$设为$y$的左子节点; 3. 将$x$的父节点设为$y$的父节点; 4. 将$y$设为$x$的右子节点; 5. 更新父节点的子节点引用(若$y$是根节点,更新根为$x$)。 **图示**: $$ \begin{array}{c} \text{旋转前} & \quad & \text{旋转后} \\ y & \quad & x \\ \uparrow & \quad & \uparrow \\ x & \quad & y \leftarrow β \\ \downarrow & \quad & \downarrow \\ β & \quad & \\ \end{array} $$ **源码示例**(参考HashMap实现): ```java // 右旋操作核心逻辑 void rotateRight(Node y) { Node x = y.left; y.left = x.right; // 步骤2 if (x.right != null) x.right.parent = y; x.parent = y.parent; // 步骤3 if (y.parent == null) root = x; // 步骤5 else if (y == y.parent.right) y.parent.right = x; else y.parent.left = x; x.right = y; // 步骤4 y.parent = x; } ``` --- #### **关键点** 1. **平衡性**:旋转通过局部调整子树高度,减少树的总高度,提升查询效率[^2]; 2. **颜色调整**:旋转后可能需要变色(如插入后修复红黑规则); 3. **时间复杂度**:单次旋转为$O(1)$,但插入/删除操作整体复杂度为$O(\log n)$[^5]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值