mirror of
https://github.com/krahets/hello-algo.git
synced 2026-08-14 12:40:58 +00:00
build
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
comments: true
|
||||
---
|
||||
|
||||
# 7.4. AVL 树 *
|
||||
# 8.4. AVL 树 *
|
||||
|
||||
在二叉搜索树章节中,我们提到了在多次插入和删除操作后,二叉搜索树可能退化为链表。这种情况下,所有操作的时间复杂度将从 $O(\log n)$ 恶化为 $O(n)$。
|
||||
|
||||
@@ -20,7 +20,7 @@ comments: true
|
||||
|
||||
G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorithm for the organization of information" 中提出了「AVL 树」。论文中详细描述了一系列操作,确保在持续添加和删除节点后,AVL 树不会退化,从而使得各种操作的时间复杂度保持在 $O(\log n)$ 级别。换句话说,在需要频繁进行增删查改操作的场景中,AVL 树能始终保持高效的数据操作性能,具有很好的应用价值。
|
||||
|
||||
## 7.4.1. AVL 树常见术语
|
||||
## 8.4.1. AVL 树常见术语
|
||||
|
||||
「AVL 树」既是二叉搜索树也是平衡二叉树,同时满足这两类二叉树的所有性质,因此也被称为「平衡二叉搜索树」。
|
||||
|
||||
@@ -448,7 +448,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
|
||||
|
||||
设平衡因子为 $f$ ,则一棵 AVL 树的任意节点的平衡因子皆满足 $-1 \le f \le 1$ 。
|
||||
|
||||
## 7.4.2. AVL 树旋转
|
||||
## 8.4.2. AVL 树旋转
|
||||
|
||||
AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉树的中序遍历序列的前提下,使失衡节点重新恢复平衡。换句话说,**旋转操作既能保持树的「二叉搜索树」属性,也能使树重新变为「平衡二叉树」**。
|
||||
|
||||
@@ -1186,7 +1186,7 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
|
||||
}
|
||||
```
|
||||
|
||||
## 7.4.3. AVL 树常用操作
|
||||
## 8.4.3. AVL 树常用操作
|
||||
|
||||
### 插入节点
|
||||
|
||||
@@ -1875,7 +1875,7 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
|
||||
|
||||
AVL 树的节点查找操作与二叉搜索树一致,在此不再赘述。
|
||||
|
||||
## 7.4.4. AVL 树典型应用
|
||||
## 8.4.4. AVL 树典型应用
|
||||
|
||||
- 组织和存储大型数据,适用于高频查找、低频增删的场景;
|
||||
- 用于构建数据库中的索引系统;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
comments: true
|
||||
---
|
||||
|
||||
# 7.3. 二叉搜索树
|
||||
# 8.3. 二叉搜索树
|
||||
|
||||
「二叉搜索树 Binary Search Tree」满足以下条件:
|
||||
|
||||
@@ -13,7 +13,7 @@ comments: true
|
||||
|
||||
<p align="center"> Fig. 二叉搜索树 </p>
|
||||
|
||||
## 7.3.1. 二叉搜索树的操作
|
||||
## 8.3.1. 二叉搜索树的操作
|
||||
|
||||
### 查找节点
|
||||
|
||||
@@ -1076,38 +1076,23 @@ comments: true
|
||||
|
||||
<p align="center"> Fig. 二叉搜索树的中序遍历序列 </p>
|
||||
|
||||
## 7.3.2. 二叉搜索树的效率
|
||||
## 8.3.2. 二叉搜索树的效率
|
||||
|
||||
假设给定 $n$ 个数字,最常见的存储方式是「数组」。对于这串乱序的数字,常见操作的效率如下:
|
||||
给定一组数据,我们考虑使用数组或二叉搜索树存储。
|
||||
|
||||
- **查找元素**:由于数组是无序的,因此需要遍历数组来确定,使用 $O(n)$ 时间;
|
||||
- **插入元素**:只需将元素添加至数组尾部即可,使用 $O(1)$ 时间;
|
||||
- **删除元素**:先查找元素,使用 $O(n)$ 时间,再在数组中删除该元素,使用 $O(n)$ 时间;
|
||||
- **获取最小 / 最大元素**:需要遍历数组来确定,使用 $O(n)$ 时间;
|
||||
|
||||
为了获得先验信息,我们可以预先将数组元素进行排序,得到一个「排序数组」。此时操作效率如下:
|
||||
|
||||
- **查找元素**:由于数组已排序,可以使用二分查找,平均使用 $O(\log n)$ 时间;
|
||||
- **插入元素**:先查找插入位置,使用 $O(\log n)$ 时间,再插入到指定位置,使用 $O(n)$ 时间;
|
||||
- **删除元素**:先查找元素,使用 $O(\log n)$ 时间,再在数组中删除该元素,使用 $O(n)$ 时间;
|
||||
- **获取最小 / 最大元素**:数组头部和尾部元素即是最小和最大元素,使用 $O(1)$ 时间;
|
||||
|
||||
观察可知,无序数组和有序数组中的各项操作的时间复杂度呈现“偏科”的特点,即有的快有的慢。**然而,二叉搜索树的各项操作的时间复杂度都是对数阶,在数据量 $n$ 较大时具有显著优势**。
|
||||
观察可知,二叉搜索树的各项操作的时间复杂度都是对数阶,具有稳定且高效的性能表现。只有在高频添加、低频查找删除的数据适用场景下,数组比二叉搜索树的效率更高。
|
||||
|
||||
<div class="center-table" markdown>
|
||||
|
||||
| | 无序数组 | 有序数组 | 二叉搜索树 |
|
||||
| ------------------- | -------- | ----------- | ----------- |
|
||||
| 查找指定元素 | $O(n)$ | $O(\log n)$ | $O(\log n)$ |
|
||||
| 插入元素 | $O(1)$ | $O(n)$ | $O(\log n)$ |
|
||||
| 删除元素 | $O(n)$ | $O(n)$ | $O(\log n)$ |
|
||||
| 获取最小 / 最大元素 | $O(n)$ | $O(1)$ | $O(\log n)$ |
|
||||
| | 无序数组 | 二叉搜索树 |
|
||||
| -------- | -------- | ----------- |
|
||||
| 查找元素 | $O(n)$ | $O(\log n)$ |
|
||||
| 插入元素 | $O(1)$ | $O(\log n)$ |
|
||||
| 删除元素 | $O(n)$ | $O(\log n)$ |
|
||||
|
||||
</div>
|
||||
|
||||
## 7.3.3. 二叉搜索树的退化
|
||||
|
||||
在理想情况下,我们希望二叉搜索树是“平衡”的,这样就可以在 $\log n$ 轮循环内查找任意节点。
|
||||
在理想情况下,二叉搜索树是“平衡”的,这样就可以在 $\log n$ 轮循环内查找任意节点。
|
||||
|
||||
然而,如果我们在二叉搜索树中不断地插入和删除节点,可能导致二叉树退化为链表,这时各种操作的时间复杂度也会退化为 $O(n)$ 。
|
||||
|
||||
@@ -1115,7 +1100,7 @@ comments: true
|
||||
|
||||
<p align="center"> Fig. 二叉搜索树的平衡与退化 </p>
|
||||
|
||||
## 7.3.4. 二叉搜索树常见应用
|
||||
## 8.3.3. 二叉搜索树常见应用
|
||||
|
||||
- 用作系统中的多级索引,实现高效的查找、插入、删除操作。
|
||||
- 作为某些搜索算法的底层数据结构。
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
comments: true
|
||||
---
|
||||
|
||||
# 7.1. 二叉树
|
||||
# 8.1. 二叉树
|
||||
|
||||
「二叉树 Binary Tree」是一种非线性数据结构,代表着祖先与后代之间的派生关系,体现着“一分为二”的分治逻辑。与链表类似,二叉树的基本单元是节点,每个节点包含一个「值」和两个「指针」。
|
||||
|
||||
@@ -135,7 +135,7 @@ comments: true
|
||||
|
||||
<p align="center"> Fig. 父节点、子节点、子树 </p>
|
||||
|
||||
## 7.1.1. 二叉树常见术语
|
||||
## 8.1.1. 二叉树常见术语
|
||||
|
||||
二叉树涉及的术语较多,建议尽量理解并记住。
|
||||
|
||||
@@ -156,7 +156,7 @@ comments: true
|
||||
|
||||
请注意,我们通常将「高度」和「深度」定义为“走过边的数量”,但有些题目或教材可能会将其定义为“走过节点的数量”。在这种情况下,高度和深度都需要加 1 。
|
||||
|
||||
## 7.1.2. 二叉树基本操作
|
||||
## 8.1.2. 二叉树基本操作
|
||||
|
||||
**初始化二叉树**。与链表类似,首先初始化节点,然后构建引用指向(即指针)。
|
||||
|
||||
@@ -422,7 +422,7 @@ comments: true
|
||||
|
||||
需要注意的是,插入节点可能会改变二叉树的原有逻辑结构,而删除节点通常意味着删除该节点及其所有子树。因此,在二叉树中,插入与删除操作通常是由一套操作配合完成的,以实现有实际意义的操作。
|
||||
|
||||
## 7.1.3. 常见二叉树类型
|
||||
## 8.1.3. 常见二叉树类型
|
||||
|
||||
### 完美二叉树
|
||||
|
||||
@@ -460,7 +460,7 @@ comments: true
|
||||
|
||||
<p align="center"> Fig. 平衡二叉树 </p>
|
||||
|
||||
## 7.1.4. 二叉树的退化
|
||||
## 8.1.4. 二叉树的退化
|
||||
|
||||
当二叉树的每层节点都被填满时,达到「完美二叉树」;而当所有节点都偏向一侧时,二叉树退化为「链表」。
|
||||
|
||||
@@ -484,7 +484,7 @@ comments: true
|
||||
|
||||
</div>
|
||||
|
||||
## 7.1.5. 二叉树表示方式 *
|
||||
## 8.1.5. 二叉树表示方式 *
|
||||
|
||||
我们通常使用二叉树的「链表表示」,即存储单位为节点 `TreeNode` ,节点之间通过指针相连接。本文前述示例代码展示了二叉树在链表表示下的各项基本操作。
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
comments: true
|
||||
---
|
||||
|
||||
# 7.2. 二叉树遍历
|
||||
# 8.2. 二叉树遍历
|
||||
|
||||
从物理结构的角度来看,树是一种基于链表的数据结构,因此其遍历方式是通过指针逐个访问节点。然而,树是一种非线性数据结构,这使得遍历树比遍历链表更加复杂,需要借助搜索算法来实现。
|
||||
|
||||
二叉树常见的遍历方式包括层序遍历、前序遍历、中序遍历和后序遍历等。
|
||||
|
||||
## 7.2.1. 层序遍历
|
||||
## 8.2.1. 层序遍历
|
||||
|
||||
「层序遍历 Level-Order Traversal」从顶部到底部逐层遍历二叉树,并在每一层按照从左到右的顺序访问节点。
|
||||
|
||||
@@ -250,7 +250,7 @@ comments: true
|
||||
|
||||
**空间复杂度**:在最差情况下,即满二叉树时,遍历到最底层之前,队列中最多同时存在 $\frac{n + 1}{2}$ 个节点,占用 $O(n)$ 空间。
|
||||
|
||||
## 7.2.2. 前序、中序、后序遍历
|
||||
## 8.2.2. 前序、中序、后序遍历
|
||||
|
||||
相应地,前序、中序和后序遍历都属于「深度优先遍历 Depth-First Traversal」,它体现了一种“先走到尽头,再回溯继续”的遍历方式。
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
comments: true
|
||||
---
|
||||
|
||||
# 7.5. 小结
|
||||
# 8.5. 小结
|
||||
|
||||
- 二叉树是一种非线性数据结构,体现“一分为二”的分治逻辑。每个二叉树节点包含一个值以及两个指针,分别指向其左子节点和右子节点。
|
||||
- 对于二叉树中的某个节点,其左(右)子节点及其以下形成的树被称为该节点的左(右)子树。
|
||||
|
||||
Reference in New Issue
Block a user