Add Dart codes to the documents. (#529)

This commit is contained in:
Yudong Jin
2023-06-02 02:40:26 +08:00
committed by GitHub
parent 041a989d33
commit 025051c81b
38 changed files with 849 additions and 96 deletions
@@ -100,6 +100,12 @@
```
=== "Dart"
```dart title=""
```
![任意类型二叉树的数组表示](binary_tree.assets/array_representation_with_empty.png)
## 优势与局限性
+54
View File
@@ -169,6 +169,12 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
```
=== "Dart"
```dart title=""
```
「节点高度」是指从该节点到最远叶节点的距离,即所经过的“边”的数量。需要特别注意的是,叶节点的高度为 0 ,而空节点的高度为 -1 。我们将创建两个工具函数,分别用于获取和更新节点的高度。
=== "Java"
@@ -251,6 +257,14 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
[class]{AVLTree}-[func]{updateHeight}
```
=== "Dart"
```dart title="avl_tree.dart"
[class]{AVLTree}-[func]{height}
[class]{AVLTree}-[func]{updateHeight}
```
### 节点平衡因子
节点的「平衡因子 Balance Factor」定义为节点左子树的高度减去右子树的高度,同时规定空节点的平衡因子为 0 。我们同样将获取节点平衡因子的功能封装成函数,方便后续使用。
@@ -315,6 +329,12 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
[class]{AVLTree}-[func]{balanceFactor}
```
=== "Dart"
```dart title="avl_tree.dart"
[class]{AVLTree}-[func]{balanceFactor}
```
!!! note
设平衡因子为 $f$ ,则一棵 AVL 树的任意节点的平衡因子皆满足 $-1 \le f \le 1$ 。
@@ -407,6 +427,12 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
[class]{AVLTree}-[func]{rightRotate}
```
=== "Dart"
```dart title="avl_tree.dart"
[class]{AVLTree}-[func]{rightRotate}
```
### 左旋
相应的,如果考虑上述失衡二叉树的“镜像”,则需要执行「左旋」操作。
@@ -479,6 +505,12 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
[class]{AVLTree}-[func]{leftRotate}
```
=== "Dart"
```dart title="avl_tree.dart"
[class]{AVLTree}-[func]{leftRotate}
```
### 先左旋后右旋
对于下图中的失衡节点 3,仅使用左旋或右旋都无法使子树恢复平衡。此时需要先左旋后右旋,即先对 `child` 执行「左旋」,再对 `node` 执行「右旋」。
@@ -572,6 +604,12 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
[class]{AVLTree}-[func]{rotate}
```
=== "Dart"
```dart title="avl_tree.dart"
[class]{AVLTree}-[func]{rotate}
```
## AVL 树常用操作
### 插入节点
@@ -658,6 +696,14 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
[class]{AVLTree}-[func]{insertHelper}
```
=== "Dart"
```dart title="avl_tree.dart"
[class]{AVLTree}-[func]{insert}
[class]{AVLTree}-[func]{insertHelper}
```
### 删除节点
类似地,在二叉搜索树的删除节点方法的基础上,需要从底至顶地执行旋转操作,使所有失衡节点恢复平衡。
@@ -742,6 +788,14 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
[class]{AVLTree}-[func]{removeHelper}
```
=== "Dart"
```dart title="avl_tree.dart"
[class]{AVLTree}-[func]{remove}
[class]{AVLTree}-[func]{removeHelper}
```
### 查找节点
AVL 树的节点查找操作与二叉搜索树一致,在此不再赘述。
+18
View File
@@ -91,6 +91,12 @@
[class]{BinarySearchTree}-[func]{search}
```
=== "Dart"
```dart title="binary_search_tree.dart"
[class]{BinarySearchTree}-[func]{search}
```
### 插入节点
给定一个待插入元素 `num` ,为了保持二叉搜索树“左子树 < 根节点 < 右子树”的性质,插入操作分为两步:
@@ -162,6 +168,12 @@
[class]{BinarySearchTree}-[func]{insert}
```
=== "Dart"
```dart title="binary_search_tree.dart"
[class]{BinarySearchTree}-[func]{insert}
```
为了插入节点,我们需要利用辅助节点 `pre` 保存上一轮循环的节点,这样在遍历至 $\text{null}$ 时,我们可以获取到其父节点,从而完成节点插入操作。
与查找节点相同,插入节点使用 $O(\log n)$ 时间。
@@ -258,6 +270,12 @@
[class]{BinarySearchTree}-[func]{remove}
```
=== "Dart"
```dart title="binary_search_tree.dart"
[class]{BinarySearchTree}-[func]{remove}
```
### 排序
我们知道,二叉树的中序遍历遵循“左 $\rightarrow$ 根 $\rightarrow$ 右”的遍历顺序,而二叉搜索树满足“左子节点 $<$ 根节点 $<$ 右子节点”的大小关系。因此,在二叉搜索树中进行中序遍历时,总是会优先遍历下一个最小节点,从而得出一个重要性质:**二叉搜索树的中序遍历序列是升序的**。
+18
View File
@@ -143,6 +143,12 @@
```
=== "Dart"
```dart title=""
```
节点的两个指针分别指向「左子节点」和「右子节点」,同时该节点被称为这两个子节点的「父节点」。当给定一个二叉树的节点时,我们将该节点的左子节点及其以下节点形成的树称为该节点的「左子树」,同理可得「右子树」。
**在二叉树中,除叶节点外,其他所有节点都包含子节点和非空子树**。例如,在以下示例中,若将“节点 2”视为父节点,则其左子节点和右子节点分别是“节点 4”和“节点 5”,左子树是“节点 4 及其以下节点形成的树”,右子树是“节点 5 及其以下节点形成的树”。
@@ -329,6 +335,12 @@
```
=== "Dart"
```dart title="binary_tree.dart"
```
**插入与删除节点**。与链表类似,通过修改指针来实现插入与删除节点。
![在二叉树中插入与删除节点](binary_tree.assets/binary_tree_add_remove.png)
@@ -445,6 +457,12 @@
```
=== "Dart"
```dart title="binary_tree.dart"
```
!!! note
需要注意的是,插入节点可能会改变二叉树的原有逻辑结构,而删除节点通常意味着删除该节点及其所有子树。因此,在二叉树中,插入与删除操作通常是由一套操作配合完成的,以实现有实际意义的操作。
@@ -76,6 +76,12 @@
[class]{}-[func]{levelOrder}
```
=== "Dart"
```dart title="binary_tree_bfs.dart"
[class]{}-[func]{levelOrder}
```
### 复杂度分析
**时间复杂度**:所有节点被访问一次,使用 $O(n)$ 时间,其中 $n$ 为节点数量。
@@ -202,6 +208,16 @@
[class]{}-[func]{postOrder}
```
=== "Dart"
```dart title="binary_tree_dfs.dart"
[class]{}-[func]{preOrder}
[class]{}-[func]{inOrder}
[class]{}-[func]{postOrder}
```
!!! note
我们也可以仅基于循环实现前、中、后序遍历,有兴趣的同学可以自行实现。