(一)利用二叉链表结构,通过先序遍历先建立起一棵二叉树如图1-1。根据建立这个的二叉树,并且通过递归的方式实现了二叉树的先序遍历、中序遍历和后序遍历三种遍历算法,用队列实现二叉树的层次遍历算法,并按层次输出(标出层号),并能统计树叶数,结点数,层高等信息,如图1-2。
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 30
// 定义一个字符类型别名,用于二叉树的元素类型
typedef char ElemType;
// 定义一个指向二叉树节点的指针类型别名
typedef struct TNode *BiTree;
// 定义二叉树节点的结构体
struct TNode
{
char data; // 节点数据
BiTree lchild; // 指向左子树的指针
BiTree rchild; // 指向右子树的指针
};
// 判断二叉树是否为空
// 参数T是指向二叉树根的指针的指针
int IsEmpty_BiTree(BiTree *T)
{
// 如果T指向的指针为NULL,说明二叉树为空
if(*T == NULL)
return 1; // 返回1,表示二叉树为空
else
return 0; // 返回0,表示二叉树不为空
}
// 创建二叉树
// 参数T是指向二叉树根的指针的指针
void Create_BiTree(BiTree *T)
{
char ch;
// 从标准输入读取一个字符
ch = getchar();
//当输入的是"#"时,认为该子树为空
if(ch == '#')
*T = NULL;// 将T指向的指针设为NULL,表示该子树为空
//创建树结点
else
{
// 动态分配内存空间给新的节点,并将地址赋值给T指向的指针
*T = (BiTree)malloc(sizeof(struct TNode));
// 设置新节点的数据
(*T)->data = ch; //生成树结点
// 递归地生成左子树
Create_BiTree(&(*T)->lchild);
// 递归地生成右子树
Create_BiTree(&(*T)->rchild);
}
}
// 先序遍历二叉树
void TraverseBiTree(BiTree T)
{
// 如果节点为空,则直接返回
if(T == NULL)
return;
else
{
// 访问节点
printf("%c ",T->data);
// 递归遍历左子树
TraverseBiTree(T->lchild);
// 递归遍历右子树
TraverseBiTree(T->rchild);
}
}
// 中序遍历二叉树
void InOrderBiTree(BiTree T)
{
// 如果节点为空,则直接返回
if(NULL == T)
return;
else
{
// 递归遍历左子树
InOrderBiTree(T->lchild);
// 访问节点
printf("%c ",T->data);
// 递归遍历右子树
InOrderBiTree(T->rchild);
}
}
// 后序遍历二叉树
void PostOrderBiTree(BiTree T)
{
// 如果节点为空,则直接返回
if(NULL == T)
return;
else
{
// 递归遍历左子树
PostOrderBiTree(T->lchild);
// 递归遍历右子树
PostOrderBiTree(T->rchild);
// 访问节点
printf("%c ",T->data);
}
}
// 计算二叉树的深度
int TreeDeep(BiTree T)
{
int deep = 0; // 初始化深度为0
if(T) // 如果树不为空
{
int leftdeep = TreeDeep(T->lchild); // 递归计算左子树的深度
int rightdeep = TreeDeep(T->rchild); // 递归计算右子树的深度
deep = leftdeep > rightdeep ? leftdeep + 1 : rightdeep + 1; // 取左右子树深度的最大值,并加1(因为根节点也算一层)
}
return deep; // 返回树的深度
}
// 统计二叉树的叶子节点数量,并打印叶子节点的值
void Leafcount(BiTree T, int *num)
{
if(T) // 如果树不为空
{
if(T->lchild == NULL && T->rchild == NULL) // 如果当前节点是叶子节点(即左右子树都为空)
{
num++; // 叶子节点数量加1
printf("%c ", T->data); // 打印叶子节点的值
}
Leafcount(T->lchild, num); // 递归遍历左子树
Leafcount(T->rchild, num); // 递归遍历右子树
}
}
// 二叉树的层序遍历(广度优先遍历)
void LevelOrder_BiTree(BiTree T)
{
// 用一个队列保存结点信息,这里的队列采用的是顺序队列中的数组实现
int front = 0; // 队列的前端指针
int rear = 0; // 队列的后端指针
BiTree BiQueue[MAXSIZE]; // 假设MAXSIZE是队列的最大容量,这里是一个数组,用于模拟队列
BiTree tempNode; // 临时节点,用于从队列中取出节点
if(T != NULL) // 如果树不为空
{
BiQueue[rear++] = T; // 将根节点入队
while(front != rear) // 当队列不为空时
{
// 取出队头元素,并使队头指针向后移动一位
tempNode = BiQueue[front++];
// 打印当前节点的值
printf("%c ", tempNode->data);
// 判断左子树是否为空,若不为空,则加入队列
if(tempNode->lchild != NULL)
BiQueue[rear++] = tempNode->lchild;
// 判断右子树是否为空,若不为空,则加入队列
if(tempNode->rchild != NULL)
BiQueue[rear++] = tempNode->rchild;
}
}
}
int main(void)
{
// 声明一个指向二叉树结构体的指针T,但这里T并没有直接分配内存
BiTree T;
int deepth, num = 0; // 声明树的深度和叶子节点数量的变量
// 调用Create_BiTree函数,通过引用传递T的地址,创建二叉树,并将根节点地址赋值给T
Create_BiTree(&T);
// 输出先序遍历结果
printf("先序遍历二叉树:\n");
TraverseBiTree(T);
printf("\n");
// 输出中序遍历结果
printf("中序遍历二叉树:\n");
InOrderBiTree(T);
printf("\n");
// 输出后序遍历结果
printf("后序遍历二叉树:\n");
PostOrderBiTree(T);
printf("\n");
// 层次遍历二叉树,即广度优先遍历
printf("层次遍历结果:");
LevelOrder_BiTree(T);
printf("\n");
// 计算树的深度
deepth = TreeDeep(T);
printf("树的深度为:%d", deepth);
printf("\n");
// 计算并输出树的叶子节点
printf("树的叶子结点为:");
Leafcount(T,&num);
printf("\n树的叶子结点个数为:%d", num);
return 0;
}
![](https://img-blog.csdnimg.cn/direct/565bd9d9ce2745e6bd8e8e63a444b419.png)
![](https://img-blog.csdnimg.cn/direct/32cb85ac1b6d495fa9089f3a4ad6465e.png)