C语言二叉树的遍历以及求节点个数、高度

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值