IDE:Visual Studio 2022
本文基于 二叉树的创建及遍历方法_利用遍历建立二叉树-CSDN博客 的细致讲解写出,
若代码某些地方有问题欢迎大家指正,谢谢!
#define _CRT_SECURE_NO_WARNINGS // 定义宏,避免使用scanf()时的警告
#include <stdio.h>
#include <stdlib.h>
// 定义二叉树节点的结构体
typedef struct BiTNode {
char data; // 节点存储的数据
struct BiTNode* l_child; // 左孩子指针
struct BiTNode* r_child; // 右孩子指针
} BiTNode, *BiTree;
// 定义栈节点的结构体
typedef struct StackNode {
BiTree data; // 存储二叉树节点的指针
struct StackNode* next; // 指向下一个栈节点的指针
} StackNode, *LinkStack;
// 初始化栈
void InitStack(LinkStack& S) {
S = NULL; // 将栈指针设置为NULL,表示空栈
}
// 入栈操作
void Push(LinkStack& S, BiTree e) {
StackNode* p; // 创建一个新的栈节点
p = (StackNode*)malloc(sizeof(StackNode)); // 动态分配内存
p->data = e; // 存储传入的二叉树节点
p->next = S; // 新节点的next指向当前栈顶
S = p; // 栈顶更新为新节点
}
// 出栈操作
void Pop(LinkStack& S, BiTree& e) {
if (S == NULL) { printf("栈空"); } // 如果栈为空,打印错误信息
else {
StackNode* p; // 创建一个临时指针
e = S->data; // 取出栈顶元素
p = S; // 临时指针指向栈顶
S = S->next; // 栈顶指针移动到下一个元素
free(p); // 释放原栈顶元素的内存
}
}
// 判断栈是否为空
int StackEmpty(LinkStack& S) {
if (S == NULL) {
return 1; // 如果栈为空,返回1
} else {
return 0; // 如果栈不为空,返回0
}
}
// 创建二叉树
void CreateBiTree(BiTree& T) {
char ch; // 用于存储输入的字符
scanf("%c", &ch); // 读取一个字符
if (ch == '#') {
T = NULL; // 如果输入的是'#',表示空节点
} else {
T = (BiTree)malloc(sizeof(BiTNode)); // 分配新的节点
T->data = ch; // 存储数据
CreateBiTree(T->l_child); // 递归创建左子树
CreateBiTree(T->r_child); // 递归创建右子树
}
}
// 前序遍历二叉树
void PreOrderTraverse(BiTree T) {
if (T) {
printf("%c ", T->data); // 访问根节点
PreOrderTraverse(T->l_child); // 遍历左子树
PreOrderTraverse(T->r_child); // 遍历右子树
}
}
// 中序遍历二叉树
void MidOrderTraverse(BiTree T) {
if (T) {
MidOrderTraverse(T->l_child); // 遍历左子树
printf("%c ", T->data); // 访问根节点
MidOrderTraverse(T->r_child); // 遍历右子树
}
}
// 非递归中序遍历二叉树
void InOrderTraverse(BiTree T) {
LinkStack S; // 创建栈
InitStack(S); // 初始化栈
BiTree p, q; // 创建两个指针
p = T; // 从根节点开始
q = (BiTree)malloc(sizeof(BiTNode)); // 分配一个临时节点
while (p || !StackEmpty(S)) { // 当前节点不为空或者栈不为空
if (p) {
Push(S, p); // 将当前节点入栈
p = p->l_child; // 移动到左子节点
} else {
Pop(S, q); // 出栈
printf("%c ", q->data); // 访问节点
p = q->r_child; // 移动到右子节点
}
}
}
// 后序遍历二叉树
void LasOrderTraverse(BiTree T) {
if (T) {
LasOrderTraverse(T->l_child); // 遍历左子树
LasOrderTraverse(T->r_child); // 遍历右子树
printf("%c ", T->data); // 访问根节点
}
}
// 计算二叉树的节点数
int NodeCount(BiTree T) {
if (T == NULL) return 0; // 如果是空树,返回0
else return NodeCount(T->l_child) + NodeCount(T->r_child) + 1; // 递归计算左右子树节点数并加1
}
// 计算二叉树的高度
int BiTreeheight(BiTree T) {
int lheight, rheight; // 左右子树的高度
if (T == NULL) return 0; // 如果是空树,返回0
else {
lheight = BiTreeheight(T->l_child); // 计算左子树高度
rheight = BiTreeheight(T->r_child); // 计算右子树高度
return lheight > rheight ? lheight + 1 : rheight + 1; // 返回左右子树中较大的高度加1
}
}
//主函数
int main() {
BiTree T; // 创建二叉树的根节点
int n, h; // 用于存储节点数和树的高度
CreateBiTree(T); // 创建二叉树
printf("先序遍历:"); // 打印遍历方式
PreOrderTraverse(T); // 执行前序遍历
printf("\n");
printf("中序遍历:");
MidOrderTraverse(T); // 执行中序遍历
printf("\n");
printf("非递归中序遍历:");
InOrderTraverse(T); // 执行非递归中序遍历
printf("\n");
printf("后序遍历:");
LasOrderTraverse(T); // 执行后序遍历
printf("\n");
n = NodeCount(T); // 计算节点数
printf("二叉树的节点个数为:%d \n", n); // 打印节点数
h = BiTreeheight(T); // 计算树的高度
printf("二叉树的高度为:%d \n", h); // 打印树的高度
return 0; // 程序结束
}
输入:
AB#CD###E#FGH##K###
输出:
先序遍历:A B C D E F G H K
中序遍历:B D C A E H G K F
非递归中序遍历:B D C A E H G K F
后序遍历:D C B H K G F E A
二叉树的节点个数为:9
二叉树的高度为:5