Release Rust code to documents. (#656)

This commit is contained in:
Yudong Jin
2023-07-26 11:00:53 +08:00
committed by GitHub
parent 60162f6fa8
commit 027bdd6510
61 changed files with 1155 additions and 145 deletions

View File

@@ -108,6 +108,12 @@
List<int?> tree = [1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15];
```
=== "Rust"
```rust title=""
```
![任意类型二叉树的数组表示](array_representation_of_tree.assets/array_representation_with_empty.png)
值得说明的是,**完全二叉树非常适合使用数组来表示**。回顾完全二叉树的定义,$\text{None}$ 只出现在最底层且靠右的位置,**因此所有 $\text{None}$ 一定出现在层序遍历序列的末尾**。这意味着使用数组表示完全二叉树时,可以省略存储所有 $\text{None}$ ,非常方便。
@@ -185,6 +191,12 @@
[class]{ArrayBinaryTree}-[func]{}
```
=== "Rust"
```rust title="array_binary_tree.rs"
[class]{ArrayBinaryTree}-[func]{}
```
## 优势与局限性
二叉树的数组表示的优点包括:

View File

@@ -182,6 +182,12 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
}
```
=== "Rust"
```rust title=""
```
「节点高度」是指从该节点到最远叶节点的距离,即所经过的“边”的数量。需要特别注意的是,叶节点的高度为 0 ,而空节点的高度为 -1 。我们将创建两个工具函数,分别用于获取和更新节点的高度。
=== "Java"
@@ -272,6 +278,14 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
[class]{AVLTree}-[func]{updateHeight}
```
=== "Rust"
```rust title="avl_tree.rs"
[class]{AVLTree}-[func]{height}
[class]{AVLTree}-[func]{update_height}
```
### 节点平衡因子
节点的「平衡因子 Balance Factor」定义为节点左子树的高度减去右子树的高度同时规定空节点的平衡因子为 0 。我们同样将获取节点平衡因子的功能封装成函数,方便后续使用。
@@ -342,6 +356,12 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
[class]{AVLTree}-[func]{balanceFactor}
```
=== "Rust"
```rust title="avl_tree.rs"
[class]{AVLTree}-[func]{balance_factor}
```
!!! note
设平衡因子为 $f$ ,则一棵 AVL 树的任意节点的平衡因子皆满足 $-1 \le f \le 1$ 。
@@ -440,6 +460,12 @@ AVL 树的特点在于「旋转 Rotation」操作它能够在不影响二叉
[class]{AVLTree}-[func]{rightRotate}
```
=== "Rust"
```rust title="avl_tree.rs"
[class]{AVLTree}-[func]{right_rotate}
```
### 左旋
相应的,如果考虑上述失衡二叉树的“镜像”,则需要执行「左旋」操作。
@@ -518,6 +544,12 @@ AVL 树的特点在于「旋转 Rotation」操作它能够在不影响二叉
[class]{AVLTree}-[func]{leftRotate}
```
=== "Rust"
```rust title="avl_tree.rs"
[class]{AVLTree}-[func]{left_rotate}
```
### 先左旋后右旋
对于下图中的失衡节点 3仅使用左旋或右旋都无法使子树恢复平衡。此时需要先左旋后右旋即先对 `child` 执行「左旋」,再对 `node` 执行「右旋」。
@@ -617,6 +649,12 @@ AVL 树的特点在于「旋转 Rotation」操作它能够在不影响二叉
[class]{AVLTree}-[func]{rotate}
```
=== "Rust"
```rust title="avl_tree.rs"
[class]{AVLTree}-[func]{rotate}
```
## AVL 树常用操作
### 插入节点
@@ -711,6 +749,14 @@ AVL 树的特点在于「旋转 Rotation」操作它能够在不影响二叉
[class]{AVLTree}-[func]{insertHelper}
```
=== "Rust"
```rust title="avl_tree.rs"
[class]{AVLTree}-[func]{insert}
[class]{AVLTree}-[func]{insert_helper}
```
### 删除节点
类似地,在二叉搜索树的删除节点方法的基础上,需要从底至顶地执行旋转操作,使所有失衡节点恢复平衡。
@@ -803,6 +849,14 @@ AVL 树的特点在于「旋转 Rotation」操作它能够在不影响二叉
[class]{AVLTree}-[func]{removeHelper}
```
=== "Rust"
```rust title="avl_tree.rs"
[class]{AVLTree}-[func]{remove}
[class]{AVLTree}-[func]{remove_helper}
```
### 查找节点
AVL 树的节点查找操作与二叉搜索树一致,在此不再赘述。

View File

@@ -97,6 +97,12 @@
[class]{BinarySearchTree}-[func]{search}
```
=== "Rust"
```rust title="binary_search_tree.rs"
[class]{BinarySearchTree}-[func]{search}
```
### 插入节点
给定一个待插入元素 `num` ,为了保持二叉搜索树“左子树 < 根节点 < 右子树”的性质,插入操作分为两步:
@@ -174,6 +180,12 @@
[class]{BinarySearchTree}-[func]{insert}
```
=== "Rust"
```rust title="binary_search_tree.rs"
[class]{BinarySearchTree}-[func]{insert}
```
为了插入节点,我们需要利用辅助节点 `pre` 保存上一轮循环的节点,这样在遍历至 $\text{None}$ 时,我们可以获取到其父节点,从而完成节点插入操作。
与查找节点相同,插入节点使用 $O(\log n)$ 时间。
@@ -275,6 +287,12 @@
[class]{BinarySearchTree}-[func]{remove}
```
=== "Rust"
```rust title="binary_search_tree.rs"
[class]{BinarySearchTree}-[func]{remove}
```
### 排序
我们知道,二叉树的中序遍历遵循“左 $\rightarrow$ 根 $\rightarrow$ 右”的遍历顺序,而二叉搜索树满足“左子节点 $<$ 根节点 $<$ 右子节点”的大小关系。因此,在二叉搜索树中进行中序遍历时,总是会优先遍历下一个最小节点,从而得出一个重要性质:**二叉搜索树的中序遍历序列是升序的**。

View File

@@ -155,6 +155,12 @@
}
```
=== "Rust"
```rust title=""
```
节点的两个指针分别指向「左子节点」和「右子节点」,同时该节点被称为这两个子节点的「父节点」。当给定一个二叉树的节点时,我们将该节点的左子节点及其以下节点形成的树称为该节点的「左子树」,同理可得「右子树」。
**在二叉树中,除叶节点外,其他所有节点都包含子节点和非空子树**。例如,在以下示例中,若将“节点 2”视为父节点则其左子节点和右子节点分别是“节点 4”和“节点 5”左子树是“节点 4 及其以下节点形成的树”,右子树是“节点 5 及其以下节点形成的树”。
@@ -358,6 +364,12 @@
n2.right = n5;
```
=== "Rust"
```rust title="binary_tree.rs"
```
**插入与删除节点**。与链表类似,通过修改指针来实现插入与删除节点。
![在二叉树中插入与删除节点](binary_tree.assets/binary_tree_add_remove.png)
@@ -486,6 +498,12 @@
n1.left = n2;
```
=== "Rust"
```rust title="binary_tree.rs"
```
!!! note
需要注意的是,插入节点可能会改变二叉树的原有逻辑结构,而删除节点通常意味着删除该节点及其所有子树。因此,在二叉树中,插入与删除操作通常是由一套操作配合完成的,以实现有实际意义的操作。

View File

@@ -80,6 +80,12 @@
[class]{}-[func]{levelOrder}
```
=== "Rust"
```rust title="binary_tree_bfs.rs"
[class]{}-[func]{level_order}
```
**时间复杂度**:所有节点被访问一次,使用 $O(n)$ 时间,其中 $n$ 为节点数量。
**空间复杂度**:在最差情况下,即满二叉树时,遍历到最底层之前,队列中最多同时存在 $\frac{n + 1}{2}$ 个节点,占用 $O(n)$ 空间。
@@ -204,6 +210,16 @@
[class]{}-[func]{postOrder}
```
=== "Rust"
```rust title="binary_tree_dfs.rs"
[class]{}-[func]{pre_order}
[class]{}-[func]{in_order}
[class]{}-[func]{post_order}
```
**时间复杂度**:所有节点被访问一次,使用 $O(n)$ 时间,其中 $n$ 为节点数量。
**空间复杂度**:在最差情况下,即树退化为链表时,递归深度达到 $n$ ,系统占用 $O(n)$ 栈帧空间。