C++ 实现二叉树的后序遍历与中序遍历构建及层次遍历输出

C++ 实现二叉树的后序遍历与中序遍历构建及层次遍历输出

目录

一、实验背景与目标

本实验旨在深入掌握二叉树的后序遍历和中序遍历构建二叉树的方法,并学习按层次遍历输出二叉树节点的算法。通过本实验,能够理解并实践如何通过后序和中序遍历信息来构建二叉树,并利用队列进行层次遍历输出。

二、实验环境

  • 开发环境:DevC++
  • 语言:C++

三、实验内容

  • 输入一个正整数 N ,表示二叉树中的节点数量。
  • 输入该二叉树的后序遍历和中序遍历序列,数字间以空格分隔。
  • 在一行中输出该树的层次遍历的序列,数字间以一个空格分隔,行首尾不得有多余空格。

四、数据结构与算法

数据结构

  1. 树节点结构体:我们使用结构体来表示树的每一个节点,其中包括节点值以及左右子树的指针。

    cpp 复制代码
    struct TreeNode {
        int val;
        TreeNode* left;
        TreeNode* right;
    };
  2. 队列:在层次遍历时,我们使用队列来保存当前需要处理的节点,队列的先进先出(FIFO)特性能够帮助我们按层次输出节点。

算法描述

1. 构建二叉树函数 buildTree

首先,根据给定的中序遍历数组 min[] 和后序遍历数组 post[],我们可以递归地构建二叉树。

  • 每次递归时,后序遍历的最后一个元素就是树的根节点。
  • 然后在中序遍历中找到根节点的位置,从而确定左子树和右子树的范围,再递归构建左右子树。
cpp 复制代码
TreeNode* buildTree(int min[], int post[], int n) {
    if (!n)
        return NULL;
    TreeNode* T = (TreeNode*)malloc(sizeof(struct TreeNode));
    T->val = post[n - 1];  // 后序遍历的最后一个节点就是树的根节点
    T->left = T->right = NULL;

    // 从中序遍历中找到根节点的位置
    int index;
    for (index = 0; index < n; index++) {
        if (min[index] == post[n - 1]) break;
    }
    T->left = buildTree(min, post, index);
    T->right = buildTree(min + index + 1, post + index, n - index - 1);
    return T;
}
2. 层次遍历函数 LevelOrder

使用队列进行层次遍历,按顺序输出二叉树的节点。队列帮助我们按层次处理每一个节点。

cpp 复制代码
void LevelOrder(TreeNode* root) {
    if (root == NULL) return;

    queue<TreeNode*> q;
    q.push(root);
    
    bool first = true;
    while (!q.empty()) {
        TreeNode* node = q.front();
        q.pop();
        
        if (first) {
            cout << node->val;
            first = false;
        } else {
            cout << " " << node->val;
        }
        
        if (node->left) q.push(node->left);
        if (node->right) q.push(node->right);
    }
}

关键代码与解释

  1. buildTree 函数:用于递归地构建二叉树。每次根据后序遍历的最后一个元素确定根节点,并在中序遍历中找到根节点的位置,从而递归构建左右子树。

  2. LevelOrder 函数:用于层次遍历输出二叉树的节点。利用队列进行层次遍历,逐个输出节点的值。

完整代码

cpp 复制代码
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
};

TreeNode* buildTree(int min[], int post[], int n) {
    if (!n)
        return NULL;
    TreeNode* T = (TreeNode*)malloc(sizeof(struct TreeNode));
    T->val = post[n - 1];  // 后序遍历的最后一个节点就是树的根节点
    T->left = T->right = NULL;

    int index;
    for (index = 0; index < n; index++) {
        if (min[index] == post[n - 1]) break;
    }
    T->left = buildTree(min, post, index);
    T->right = buildTree(min + index + 1, post + index, n - index - 1);
    return T;
}

void LevelOrder(TreeNode* root) {
    if (root == NULL) return;

    queue<TreeNode*> q;
    q.push(root);
    
    bool first = true;
    while (!q.empty()) {
        TreeNode* node = q.front();
        q.pop();
        
        if (first) {
            cout << node->val;
            first = false;
        } else {
            cout << " " << node->val;
        }
        
        if (node->left) q.push(node->left);
        if (node->right) q.push(node->right);
    }
}

int main() {
    int N;
    cin >> N;
    
    int post[N], min[N];
    for (int i = 0; i < N; i++) cin >> post[i];
    for (int i = 0; i < N; i++) cin >> min[i];
    
    TreeNode* root = buildTree(min, post, N);
    LevelOrder(root);
    
    return 0;
}

五、实验结果

六、总结与思考

通过这次实验,我们掌握了二叉树的构建方法以及层次遍历算法。理解了如何根据后序遍历和中序遍历序列构建二叉树,并学习了如何使用队列进行层次遍历输出。此算法在实际应用中非常重要,特别是在树的遍历、图的搜索等领域。

希望通过这个实验,能够为大家深入理解二叉树的操作和算法提供帮助。

相关推荐
爱和冰阔落8 小时前
【Linux】条件变量为什么必须配合互斥锁:从 pthread_cond_wait 到阻塞队列
linux·运维·c++·缓存·中间件·安卓
tedcloud1238 小时前
God‘s Eye View 怎么搭建?在云服务器上部署一个实时 3D 地球可视化平台
linux·服务器·开发语言·后端·rust
星间都市山脉8 小时前
Android16 SystemService.onBootPhase 调用时机
android·java·linux·windows·ubuntu
深入云栈8 小时前
Netty 4.2.x 源码深度解析 (十三):Epoll 传输 —— Linux 高性能 IO 的 Netty 实现
java·后端
初願致夕霞8 小时前
Linux 进程间通信(IPC)机制详解:管道、FIFO 与 System V 共享内存
linux·服务器·c++
ynchyong8 小时前
Linux nohup 后台服务合并标准错误输出到一个文件
java·linux·运维
用户3126874877208 小时前
Lombok 的 @Data 到底怎么工作的?Java 注解处理器实战全链路拆解
java
Tairitsu_H8 小时前
[C++] C++11 Lambda与包装器深度解析
开发语言·c++·c++11·lambda·包装器
傲世仙尊8 小时前
从磁盘硬件到Ext文件系统-Linux磁盘级文件系统学习笔记
linux·运维·服务器·开发语言·c++
小羊没烦恼!9 小时前
Memory 记忆设计讨论:为什么 Agent Memory 不能只靠向量数据库?
java·开发语言·windows·算法·c#