JavaGuide/docs/cs-basics/data-structure/red-black-tree.md

94 lines
4.1 KiB
Markdown
Raw Permalink Normal View History

---
title: 红黑树
category: 计算机基础
tag:
- 数据结构
---
## 红黑树介绍
红黑树Red Black Tree是一种自平衡二叉查找树。它是在 1972 年由 Rudolf Bayer 发明的,当时被称为平衡二叉 B 树symmetric binary B-trees。后来在 1978 年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的“红黑树”。
2023-10-29 10:51:15 +08:00
由于其自平衡的特性,保证了最坏情形下在 O(logn) 时间复杂度内完成查找、增加、删除等操作,性能表现稳定。
2023-10-29 10:51:15 +08:00
在 JDK 中,`TreeMap`、`TreeSet` 以及 JDK1.8 的 `HashMap` 底层都用到了红黑树。
## 为什么需要红黑树?
红黑树的诞生就是为了解决二叉查找树的缺陷。
2023-10-29 10:51:15 +08:00
二叉查找树是一种基于比较的数据结构,它的每个节点都有一个键值,而且左子节点的键值小于父节点的键值,右子节点的键值大于父节点的键值。这样的结构可以方便地进行查找、插入和删除操作,因为只需要比较节点的键值就可以确定目标节点的位置。但是,二叉查找树有一个很大的问题,就是它的形状取决于节点插入的顺序。如果节点是按照升序或降序的方式插入的,那么二叉查找树就会退化成一个线性结构,也就是一个链表。这样的情况下,二叉查找树的性能就会大大降低,时间复杂度就会从 O(logn) 变为 O(n)。
2023-10-29 10:51:15 +08:00
红黑树的诞生就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。
2023-10-29 10:51:15 +08:00
2023-12-30 17:14:13 +08:00
## **红黑树特点**
2023-10-29 10:51:15 +08:00
1. 每个节点非红即黑。黑色决定平衡,红色不决定平衡。这对应了 2-3 树中一个节点内可以存放 1~2 个节点。
2. 根节点总是黑色的。
3. 每个叶子节点都是黑色的空节点NIL 节点)。这里指的是红黑树都会有一个空的叶子节点,是红黑树自己的规则。
4. 如果节点是红色的,则它的子节点必须是黑色的(反之不一定)。通常这条规则也叫不会有连续的红色节点。一个节点最多临时会有 3 个节点,中间是黑色节点,左右是红色节点。
2024-03-17 21:11:37 +08:00
5. 从任意节点到它的叶子节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度)。每一层都只是有一个节点贡献了树高决定平衡性,也就是对应红黑树中的黑色节点。
2023-10-29 10:51:15 +08:00
正是这些特点才保证了红黑树的平衡,让红黑树的高度不会超过 2log(n+1)。
2023-10-29 10:51:15 +08:00
## 红黑树数据结构
建立在 BST 二叉搜索树的基础上AVL、2-3 树、红黑树都是自平衡二叉树(统称 B-树)。但相比于 AVL 树,高度平衡所带来的时间复杂度,红黑树对平衡的控制要宽松一些,红黑树只需要保证黑色节点平衡即可。
2023-10-29 10:51:15 +08:00
## 红黑树结构实现
```java
public class Node {
public Class<?> clazz;
public Integer value;
public Node parent;
public Node left;
public Node right;
// AVL 树所需属性
public int height;
// 红黑树所需属性
public Color color = Color.RED;
2023-12-30 17:14:13 +08:00
2023-10-29 10:51:15 +08:00
}
```
### 1.左倾染色
![幻灯片1](./pictures/红黑树/红黑树1.png)
2023-10-29 10:51:15 +08:00
- 染色时根据当前节点的爷爷节点,找到当前节点的叔叔节点。
- 再把父节点染黑、叔叔节点染黑,爷爷节点染红。但爷爷节点染红是临时的,当平衡树高操作后会把根节点染黑。
### 2.右倾染色
![幻灯片2](./pictures/红黑树/红黑树2.png)
2023-10-29 10:51:15 +08:00
### 3.左旋调衡
#### 3.1 一次左旋
2023-10-29 10:51:15 +08:00
![幻灯片3](./pictures/红黑树/红黑树3.png)
2023-10-29 10:51:15 +08:00
#### 3.2 右旋+左旋
2023-10-29 10:51:15 +08:00
![幻灯片4](./pictures/红黑树/红黑树4.png)
2023-10-29 10:51:15 +08:00
### 4.右旋调衡
#### 4.1 一次右旋
2023-10-29 10:51:15 +08:00
![幻灯片5](./pictures/红黑树/红黑树5.png)
2023-10-29 10:51:15 +08:00
#### 4.2 左旋+右旋
2023-10-29 10:51:15 +08:00
![幻灯片6](./pictures/红黑树/红黑树6.png)
2023-10-29 10:51:15 +08:00
## 文章推荐
- [《红黑树深入剖析及 Java 实现》 - 美团点评技术团队](https://zhuanlan.zhihu.com/p/24367771)
- [漫画:什么是红黑树? - 程序员小灰](https://juejin.im/post/5a27c6946fb9a04509096248#comment)(也介绍到了二叉查找树,非常推荐)
2023-10-27 06:44:02 +08:00
<!-- @include: @article-footer.snippet.md -->