完成并查集

This commit is contained in:
lifei
2020-12-04 22:24:09 +08:00
parent a772f21b42
commit bd87670363
16 changed files with 224 additions and 16 deletions

View File

@@ -1,9 +1,11 @@
{
"cSpell.words": [
"firstchild",
"infty",
"inorder",
"lchild",
"ltag",
"nextsibling",
"nextval",
"nlog",
"postorder",

View File

@@ -276,19 +276,19 @@ $$
## 6. [树与二叉树](ch5/README.md#树与二叉树)
- 二叉树
- 二叉树的基本概念
- 定义及特点
- 二叉树的存储结构
- 二叉树的遍历
- 索二叉树
- 二叉树的应用
- 二叉排序树
- 平衡二叉树
- 哈夫曼树和哈夫曼编码
- 树和森林
- 树的基本概念
- 树的存储结构
- 树和森林的遍历
- 树和森林及二叉树的转换
- 树的应用:查并集
- [二叉树](ch5/binary-tree/README.md#二叉树)
- [二叉树的基本概念](ch5/binary-tree/README.md#二叉树)
- [定义及特点](ch5/binary-tree/README.md#4-二叉树的性质)
- [二叉树的存储结构](ch5/binary-tree-storage/README.md#二叉树的存储结构)
- [二叉树的遍历](ch5/binary-tree-traversal/README.md#二叉树的遍历)
- [线索二叉树](ch5/binary-tree-traversal/README.md#7-线索二叉树)
- [二叉树的应用]()
- [二叉排序树]()
- [平衡二叉树]()
- [哈夫曼树和哈夫曼编码]()
- [树和森林](ch5/README.md#树与二叉树)
- [树的基本概念](ch5/README.md#1-树的基本概念)
- [树的存储结构](ch5/tree-storage/README.md#树的存储结构)
- [树和森林的遍历](ch5/tree-traversal/README.md#树与森林)
- [树和森林及二叉树的转换](ch5/tree-traversal/README.md#树与森林)
- [树的应用:查并集](ch5/tree-applications/README.md#1-并查集)

View File

@@ -83,3 +83,40 @@ $n$ 个结点的树中只有 $n-1$ 条边。
- 后序线索二叉树
#### 4.7.2. [线索二叉树的构造](binary-tree-traversal/README.md#72-线索二叉树的构造)
## 5. [树的存储结构](tree-storage/README.md#树的存储结构)
- [双亲表示法](tree-storage/README.md#1-双亲表示法)
- [孩子表示法](tree-storage/README.md#2-孩子表示法)
- [孩子兄弟表示法](tree-storage/README.md#3-孩子兄弟表示法)
| | 优点 | 缺点 |
| -------------- | ------------------------------------------------ | ------------------------ |
| 双亲表示法 | 寻找结点的双亲结点效率高 | 寻找结点的孩子结点效率低 |
| 孩子表示法 | 寻找结点的孩子结点效率高 | 寻找结点的双亲结点效率低 |
| 孩子兄弟表示法 | 寻找结点的孩子结点效率高,方便实现树转换为二叉树 | 寻找结点的双亲结点效率低 |
## 6. [树与森林](tree-traversal/README.md#树与森林)
- [树与二叉树的转换](tree-traversal/README.md#1-树与二叉树的转换)
- [森林与二叉树的转换](tree-traversal/README.md#2-森林与二叉树的转换)
[树的遍历](tree-traversal/README.md#3-树的遍历)
- [先根遍历](tree-traversal/README.md#31-先根遍历)
- [后根遍历](tree-traversal/README.md#32-后根遍历)
- [层次遍历](tree-traversal/README.md#33-层次遍历)
[森林的遍历](tree-traversal/README.md#4-森林的遍历)
- [先序遍历](tree-traversal/README.md#41-先序遍历)
- [中序遍历](tree-traversal/README.md#42-中序遍历)
| 树 | 森林 | 二叉树 |
| -------- | -------- | -------- |
| 先根遍历 | 先序遍历 | 先序遍历 |
| 后根遍历 | 中序遍历 | 中序遍历 |
## 7. [树的应用](tree-applications/README.md)
- [并查集](tree-applications/README.md#1-并查集)

View File

@@ -0,0 +1,48 @@
# 树的应用
## 1. 并查集
一种简单的集合表示。
通常用书的双亲表示法作为并查集的存储结构。
通常用数组元素的下标代表元素名,用根结点的下标代表子集合名,根结点的双亲结点为负数。
- `Initial(S)`:将集合 $S$ 的每个元素都初始化为只有一个单元素的子集合。
- `Union(S, Root1, Root2)`:将集合 $S$ 的子集合(互不相交) $Root2$ 并入到子集合 $Root1$。
- `Find(S, x)`:查找集合 $S$ 中单元素 $x$ 所在的子集合,并返回该子集合的名字。
![并查集1](and-search-set1.png)
![并查集2](and-search-set2.png)
```cpp
#define SIZE 100
void Initial(int S[])
{
for (int i = 0; i < size; i++)
{
S[i] = -1;
}
}
```
```cpp
int Find(int S[], int x)
{
while (S[x] >= 0)
{
x = S[x];
}
return x;
}
```
```cpp
void Union(int S[], int Root1, int Root2)
{
S[Root2] = Root1;
}
```
![并查集3](and-search-set3.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 KiB

View File

@@ -0,0 +1,62 @@
# 树的存储结构
## 1. 双亲表示法
采用一组连续的存储空间来存储每个结点,同时在每个结点中增设一个伪指针,指示双亲结点在数组的位置。
根结点的下标为 $0$,其伪指针域为 $-1$。
```cpp
#define MAX_TREE_SIZE 100
typedef struct
{
ElemType data;
int parent;
} PTNode;
typedef struct
{
PTNode nodes[MAX_TREE_SIZE];
int n;
} PTree;
```
![双亲表示法](parental-representation.png)
## 2. 孩子表示法
将每个结点的孩子结点都用单链表链接起来形成一个线性结构,$n$ 个结点具有 $n$ 个孩子链表。
```cpp
#define MAX_TREE_SIZE 100
typedef struct
{
int child;
struct CNode *next;
} CNode;
typedef struct
{
ElemType data;
struct CNode *child;
} PNode;
typedef struct
{
PNode nodes[MAX_TREE_SIZE];
int n;
} CTree;
```
![孩子表示法](child-representation.png)
## 3. 孩子兄弟表示法
以二叉链表作为树的存储结构,又称二叉树表示法。(左孩子右兄弟)
```cpp
typedef struct CSNode
{
ElemType data;
struct CSNode *firstchild, *nextsibling;
} CSNode, CSTree;
```
![孩子兄弟表示法](child-brother-representation.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

View File

@@ -0,0 +1,59 @@
# 树与森林
## 1. 树与二叉树的转换
- 树转二叉树:每个结点左指针指向它的第一个孩子结点,右指针指向它在树中相邻兄弟结点。
- 二叉树转树:每个结点都指向他们的双亲结点。
## 2. 森林与二叉树的转换
- 森林转二叉树:将每一棵树转换为二叉树,将每棵二叉树的根依次作为上一棵二叉树的右子树。
- 二叉树转森林
## 3. 树的遍历
按照某种方式访问树中的每个结点,且仅访问一次。
### 3.1. 先根遍历
若树非空,则先访问根结点,再按从左到右的顺序遍历根结点的每棵子树。
**树的先根遍历序列与这棵树的对应二叉树的先序遍历序列相同。**
![树的先根遍历](tree-preorder-traversal.png)
### 3.2. 后根遍历
若树非空,则先按从左到右的顺序遍历根结点的每棵子树,再访问根结点,
**树的后根遍历序列与这棵树的对应二叉树的中序遍历序列相同。**
![树的后根遍历](tree-postorder-traversal.png)
### 3.3. 层次遍历
## 4. 森林的遍历
### 4.1. 先序遍历
若森林非空,则,
- 访问森林中第一棵树的根结点
- 先序遍历第一棵树的子树森林
- 先序遍历除去第一棵树之后剩余的树构成的子树森林
**森林的先序遍历序列与森林对应二叉树的先序遍历序列相同。**
![森林的中序遍历](forest-preorder-traversal.png)
### 4.2. 中序遍历
若森林非空,则,
- 中序遍历第一棵树的根结点的子树森林
- 访问第一棵树的根结点
- 中序遍历除去第一棵树之后剩余的树构成的子树森林
**森林的中序遍历序列与森林对应二叉树的中序遍历序列相同。**
![森林中序遍历](forest-inorder-traversal.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 KiB