### 二叉树的建立与遍历
#### 题目背景及需求分析
本题旨在使用C语言实现二叉树的基本操作,包括构建二叉树以及对其执行三种不同的遍历方式:先序遍历、中序遍历和后序遍历。此外,还需要计算并输出二叉树的深度以及叶子节点的数量。
#### 数据结构设计
为了实现这些功能,我们需要定义一个二叉树的结构体,通常称为`BiTNode`,每个节点包含三个成员:一个字符类型的`data`字段用于存储节点数据,两个指向`BiTNode`类型的指针`lchild`和`rchild`分别代表左子树和右子树。
```c
typedef struct BiTNode {
char data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
```
#### 二叉树的构建
根据题目要求,我们需要从键盘接收一系列字符来构建二叉树。这里的字符可以用作节点的数据值,而特殊字符`#`表示空节点。通过递归的方式构建二叉树,即每次读取一个字符,如果为`#`则返回`NULL`,否则创建一个新的节点,并递归地构建其左右子树。
```c
BiTree Create(BiTree T) {
char ch;
ch = getchar();
if (ch == '#') {
T = NULL;
} else {
T = (BiTNode *)malloc(sizeof(BiTNode));
if (!T) {
printf("Error!");
return NULL;
}
T->data = ch;
T->lchild = Create(T->lchild);
T->rchild = Create(T->rchild);
}
return T;
}
```
#### 遍历算法
接下来是遍历算法的实现,其中包括先序遍历、中序遍历和后序遍历。每种遍历都有其特定的访问顺序:
- **先序遍历**:访问根节点 -> 遍历左子树 -> 遍历右子树
- **中序遍历**:遍历左子树 -> 访问根节点 -> 遍历右子树
- **后序遍历**:遍历左子树 -> 遍历右子树 -> 访问根节点
这三种遍历均采用递归的方式实现。
```c
void Preorder(BiTree T) {
if (T) {
printf("%c ", T->data);
Preorder(T->lchild);
Preorder(T->rchild);
}
}
void Inorder(BiTree T) {
if (T) {
Inorder(T->lchild);
printf("%c ", T->data);
Inorder(T->rchild);
}
}
void Postorder(BiTree T) {
if (T) {
Postorder(T->lchild);
Postorder(T->rchild);
printf("%c ", T->data);
}
}
```
#### 叶子节点数量与树的深度
为了统计叶子节点的数量,我们定义一个递归函数`Sumleaf`,该函数递归地遍历整棵树,当遇到叶子节点时计数器加一。
```c
int Sumleaf(BiTree T) {
int sum = 0, m, n;
if (T) {
if (!T->lchild && !T->rchild) {
sum++;
}
m = Sumleaf(T->lchild);
n = Sumleaf(T->rchild);
sum += m + n;
}
return sum;
}
```
对于树的深度,我们可以定义另一个递归函数`Depth`来计算。该函数同样遍历整棵树,对于每个节点,它计算左右子树的最大深度,并加1(当前节点)得到整个子树的深度。
```c
int Depth(BiTree T) {
int dep = 0, depl, depr;
if (T) {
depl = Depth(T->lchild);
depr = Depth(T->rchild);
dep = 1 + (depl > depr ? depl : depr);
}
return dep;
}
```
#### 主函数
在主函数中,我们首先调用`Create`函数构建二叉树,然后依次调用遍历函数,并输出叶子节点的数量和树的深度。
```c
int main() {
BiTree T;
int sum, dep;
T = Create(NULL);
printf("Preorder traversal: ");
Preorder(T);
printf("\nInorder traversal: ");
Inorder(T);
printf("\nPostorder traversal: ");
Postorder(T);
printf("\nNumber of leaves: %d\n", Sumleaf(T));
printf("Tree depth: %d\n", Depth(T));
return 0;
}
```
#### 测试与调试
为了验证程序的正确性,我们需要提供一组或多组测试数据,并确保程序能正确处理这些数据。同时,还应考虑异常情况,如输入非法字符或数据溢出等。
#### 总结
本篇介绍了一种使用C语言实现二叉树及其遍历的方法。通过对二叉树的构造和遍历,不仅可以加深对二叉树概念的理解,还能掌握递归算法的应用技巧。此外,通过计算叶子节点数量和树的深度,进一步增强了对树形数据结构特性的理解。