数据结构-红黑树

红黑树是一种2-3查找树的一种简洁实现。本文从2-3查找树的概念开始,逐步介绍红黑树的实现原理。

从2-3树开始

2-3树运行每个节点保存1个或者两个的值。对于普通的2节点(2-node),他保存1个key和左右两个自己点。对应3节点(3-node),保存两个Key。

2-3查找树的定义如下:

1、要么为空,要么:

2、是一个2节点,该节点保存一个key及对应value,以及两个指向左右节点的节点

3、对于3节点,该节点保存两个key及对应value,以及三个指向左中右的节点。

2-3 树的查找

2-3树的插入

往一个2-node节点插入

首先要进行查找,然后将节点挂到未找到的节点上。

如果查找后未找到的节点是一个2-node节点,那么很容易,我们只需要将新的元素放到这个2-node节点里面使其变成一个3-node节点即可。

 往一个3-node节点插入

1、只包含一个3-node节点。

暂时使其变成一个4-node节点,然后,我们将这个4-node节点的中间元素提升,左边的节点作为其左节点,右边的元素作为其右节点。

插入完成,变为平衡2-3查找树,树的高度从0变为1。

 2、节点是3-node,父节点是2-node

同理,临时的4-node节点提升,此时高度加一,再使原父节点和提升后的节点合并成3-node 节点,高度减一。

 3、节点是3-node,父节点也是3-node

节点临时的4-node节点提升,此时高度加一,再使临时4-node节点的父节点的父节点和提升后的节点合并成一个新节点,高度减一。重复操作,直到新节点是一个2-3节点。

        总结:

        4-node节点拆分成2-3node涉及的操作有6种:

                在root;

                在2-node 节点的左右;

                在3-node 节点的左中右;

对于4-node节点变形为2-3节点,变形前后树的高度没有发生变化。只有当跟节点是4-node节点,变形后树的高度才加一。如下图所示:64-node 变形的可能情况)

 红黑树

首先,红黑树和avl树都是自平衡树,但是定义不同,表现有所区别。AVL树要求它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1,红黑树要求所有的黑色连接是一个完全平衡的二叉树。

“ 红黑树的主要是想对2-3查找树进行编码,以约定的编码形式使用2-node 节点表示3-nodes,从而实现2-3 查找树。”这样做使2-3节点的实现在2节点的树中完成。

红黑树是一种具有红色和黑色链接的平衡查找树,同时满足:

  • 红色节点向左倾斜 (减少3-nodes节点的类型)
  • 一个节点不可能有两个红色链接 (两个红色节点对应为4-nodes 节点;特别的,为了满足此规定,对红黑树变色,这也是红黑树中唯一触发变色的条件)
  • 整个完全黑色平衡,即从根节点到所以叶子结点的路径上,黑色链接的个数都相同。(为一个平衡的2-3 树)

实现

原理:按照2-3 树的逻辑,从一个root开始,逐步添加所有的节点,这是生成树的基本步骤。可以假设每次添加前,树都是“平衡的”,加入一个node时,2-3树平衡化保证树的维持平衡(2node 变成 3-node 高度不变;3-node变为 4-node,变形后高度加一,将head向上归并,最后高度不变或最终root拆分,整颗树高度加一)

定义:

1、在二叉查找树的每一个节点上增加一个新的表示颜色的标记。该标记指示该节点指向其父节点的颜色。

2、新插入的节点使用红色链接。并约定红色节点向左倾斜。

3、左旋,右旋,和颜色转换如下图:( H 表示触发动作的节点位置。该图表示以红色节点向左倾斜为前提的所有操作。)

在左转和右转的过程中,链接颜色不变。唯一触发改变颜色的条件是出现4-node 节点,即为出现两个子节点为红色节点。

### Java 中红黑树数据结构实现与应用 #### 红黑树简介 红黑树是一种自平衡二叉查找,在计算机科学中用于高效地存储和检索键值对。该数据结构的特点在于其能够自动调整节点位置来维持一定的平衡条件,从而保证最坏情况下的时间复杂度为 O(log n)[^1]。 #### 平衡特性对比 相较于 AVL 而言,尽管两者都致力于维护二叉查找的高度接近于最小可能高度,但是由于红黑树对于旋转次数的要求较低,因此在频繁发生插入或删除的情况下现更优;而像 `TreeMap` 和 `TreeSet` 这样的集合类正是利用这一点实现了高效的增删改查功能[^2]。 #### 关键属性定义 为了满足上述提到的性质,每棵红黑树中的结点除了拥有指向左右子以及父辈指针外还需要额外记录颜色信息(红色/黑色),具体如下所示: ```java private static final boolean RED = false; private static final boolean BLACK = true; static class Node<K,V> { K key; // 存储的关键字 V value; // 对应关键字所映射的对象 Node<K,V> left; // 左孩子引用 Node<K,V> right; // 右孩子引用 Node<K,V> parent;// 父亲引用 boolean color; // 颜色标记 public Node(K key, V value, Node<K,V> parent){ this.key=key; this.value=value; this.parent=parent; this.color=RED; // 新加入的节点默认设为红色 } } ``` #### 插入操作逻辑 当向一棵已有的红黑树内添加新元素时,会先按照普通的 BST 方式找到合适的位置并创建新的叶子节点。之后再依据一系列规则判断是否需要执行重涂色或是旋转变换以恢复整棵应有的形态特征。 - 如果当前新增加的是根,则直接将其变为黑色; - 若祖父存在且叔叔也为红色,则将父亲、叔叔均改为黑色并将祖父变更为红色继续向上处理; - 当仅有单侧兄弟呈红色状态时可通过一次左(右)转使得双亲成为临时性的“假”根以便后续统一调整; - 剩余情形下只需简单交换父子间染色即可完成修复工作。 以上过程可以概括成一段伪代码形式示出来: ```pseudo function insertFixup(node) if node is root then set its color to black and return. while (node != null && node's parent is red) // 处理违反红黑树特性的几种场景... end while ``` 实际上完整的算法较为复杂,涉及到多个分支路径的选择问题,这里仅给出大致思路供理解参考之用。 #### 删除操作概述 移除某个指定项的过程同样遵循着相似的原则——即先依照普通二叉搜索的方式定位目标对象所在位置,并考虑三种不同类型的状况分别采取相应的措施加以应对:如果待消除的目标恰好处于末端处那么可以直接摘掉它而不影响其他部分;反之则需寻找合适的替代品填补空缺后再做进一步讨论。 值得注意的是在整个过程中可能会引入一些暂时不符合标准的情况,这就要求我们及时作出必要的修正动作直至最终达到稳定为止。 #### 应用实例分析 正如前面提及的一样,红黑树广泛应用于各种编程语言的标准库当中作为内部机制支撑起诸如有序之类的抽象容器类型。例如在 JDK8 版本以后版本里头,`HashMap` 的链地址法解决哈希冲突方案便采用了基于红黑树优化后的链结构,以此提高极端情况下访问效率的同时兼顾了空间利用率方面的需求。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值