(pat-a)1020. Tree Traversals (25)

本文介绍如何利用二叉树的后序遍历和中序遍历来构建二叉树,并实现层序遍历算法。通过具体示例详细解析了构建过程及代码实现。

题目:题目链接,给出二叉树的后序、中序,求层序。

首先这里有个知识点,就是二叉树的搜索(遍历)分为几种:

  • 前序,pre order
  • 中序,in order
  • 后序,post order
  • 层次遍历,level order

其实前三种都属于二叉树的深搜(DFS),层次遍历就是广搜(BFS)。在这里要注意的是,如果想要唯一确定一棵二叉树,至少要给出“中序”;如果只知道前序、后序,是不能唯一确定一棵树的。

解题思路:根据给出的2个序列,建立起一棵二叉树。然后再对这棵树进行BFS。所以关键是建树的过程。

在这道题中,是根据后序和中序,去确立一颗树。其实算法的过程可以说是在模拟我们在纸上思考的过程。
根据PAT网站给出的测例,说明一下这个过程。
测例:

后序: 2 3 1 5 7 6 4
中序: 1 2 3 4 5 6 7

算法过程:

( 从整个序列开始)先看后序,最后一个是4,那么根结点就是4。然后在中序那里找到4,把中序分成3部分:123、4、567,分别对应左子树,根,右子树。然后根据子树的结点数(左子树有3个点,右子树有3个点),后序也相应地分成3部分:231、 576、 4:
这里写图片描述
然后对左子树子序列(“123”)和右子树的子序列(“567”)递归地进行上述过程,便构造出一棵树了。
如果看到这里还不是太明白,我们可以把该算法再走一会儿:

  • 我们先走左子树。中序为:123,后序为:231。同样,在后序中发现“1”是局部根结点,那么只剩下右子树“23”。如图:
    这里写图片描述

  • 中序的“23”对应后序的“23”,那么“3”就是局部根结点,“2”就是其左结点了:(这里的左子树只剩下一个结点,整棵树的左边的递归终止)
    这里写图片描述

  • 剩下就是整棵树的右边“567”了,相信大家已经会自己演绎了,那剩下的就是代码的事情了。

代码:(代码粗糙,不过我会以注释的形式去说明一些关键的部分):

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

/* 二叉树的结点 */
struct Node {
    int element;
    Node* left;
    Node* right;

    Node() {
        element = -1;
        left = right = NULL;
    }

    Node(int e, Node* l = NULL, Node* r = NULL) {
        this->element = e;
        this->left = l;
        this->right = r;
    }
};

/* 二叉树。在Node层上再抽象出BTree一层是为了方便操作 */
class BTree {
public:
    BTree() {
        root = NULL;
    }

    BTree(Node* node) {
        root = node;
    }

    ~BTree() {
        clear(root);
    }

    vector<int> bfs() const {
        Node* tmp = root;
        vector<int> resultList;
        queue<Node*> Q;
        Q.push(tmp);
        while (!Q.empty()) {
            Node* curNode = Q.front();
            Q.pop();

            // current
            resultList.push_back(curNode->element);

            // next
            if (curNode->left != NULL) {
                Q.push(curNode->left);
            }
            if (curNode->right != NULL) {
                Q.push(curNode->right);
            }
        }
        return resultList;
    }

private:
    Node* root; // 存储根结点

    /* 注意,释放一棵树的堆内存,需要采取后序的方式 */
    void clear(Node* root) {
        if (root == NULL) return;
        clear(root->left);
        clear(root->right);
        delete root;
    }
};

const int CASE_NUM = 1;
const int MAX_NODE_NUM = 30;
int nodenum;
int postOrder[MAX_NODE_NUM], inOrder[MAX_NODE_NUM];

/* 递归地 建立起一棵二叉树 */
Node* buildTree(int postLeft, int postRight, int inLeft, int inRight) {
    if (inRight <= inLeft || postRight <= postLeft) return NULL; // 递归的终止条件

    int rootElement = postOrder[postRight - 1]; // 后序子序列中最后一个就是根结点
    Node* ret = new Node(rootElement); // 分配内存,建立根结点
    int pos;
    // 然后在中序子序列中定位根结点的位置
    for (int i = inLeft; i < inRight; ++i) {
        if (rootElement == inOrder[i]) {
            pos = i; // pos就是根结点的位置
            break;
        }
    }
    // 因为在中序中,根结点一旦确定,那么它左边的序列就是左子树,右边的序列就是右子树
    int leftCount = pos - inLeft; // 左边序列的长度
    int rightCount = inRight - pos; // 右边序列的长度

    ret->left = buildTree(postLeft, postLeft + leftCount, inLeft, pos); // 递归:对左子树再进行建树的过程
    ret->right = buildTree(postLeft + leftCount, postRight - 1, pos + 1, inRight); // 递归:对右子树进行建树

    return ret; // 返回当前根结点(局部根结点)
}


int main() {
    int casenum = CASE_NUM;
    while (casenum--) {

        // 处理输入
        cin >> nodenum;
        for (int i = 0; i < nodenum; ++i) {
            cin >> postOrder[i];
        }
        for (int i = 0; i < nodenum; ++i) {
            cin >> inOrder[i];
        }

        // 建树
        Node* root = buildTree(0, nodenum, 0, nodenum);
        BTree* bTree = new BTree(root);

        // 按照格式输出结果
        vector<int> levelOrder = bTree->bfs();
        for (int i = 0, len = levelOrder.size(); i < len; ++i) {
            cout << levelOrder[i];
            if (i == len - 1) {
                cout << endl;
            } else {
                cout << ' ';
            }
        }

        delete bTree; // 记得释放堆内存哦!
    }

    return 0;
}
Beyond Compare是一款文件差异比较工具的文件和文件夹比较工具,使用该工具可以可视化和调整差异, 合并修改,同步文件夹。支持文件夹比较,文件夹合并和同步,文本比较,表格比较,图片比较,16进制比较,注册表比较,版本比较等;调整差异,合并修改,内置文件浏览器可以针对文件、文件夹之间的差异对比及上传同步。 Beyond Compare 5.0.4.30422是一款先进的文件和文件夹比较工具,它能够帮助用户高效地识别和管理文件差异,支持多种文件类型和格式的比较。使用Beyond Compare,用户可以轻松地对文件夹内容进行同步,无论是进行简单的文件复制还是复杂的项目同步任务。此外,该工具还具备了高级的文件比较功能,如文本比较、表格比较、图片比较、16进制比较以及注册表比较,覆盖了从纯文本到二进制文件的广泛使用场景。 对于文本文件的比较,Beyond Compare提供了语法高亮和行号等辅助功能,让用户在审查代码或文档时能更快地定位差异点。表格比较功能则特别适用于数据分析和处理任务,可以快速识别两个Excel电子表格之间的不同之处。在进行图片文件的比较时,用户可以通过直观的视图了解图片之间的微小差别,这在图像处理和质量控制中尤其有用。 此外,16进制比较功能为开发者提供了深入分析二进制文件差异的手段,无论是在软件开发还是在数据恢复方面都大有裨益。注册表比较则专注于Windows系统的核心配置文件,帮助IT专业人员快速定位系统配置的变化,这对于系统维护和故障排除尤其重要。 Beyond Compare内置的文件浏览器允许用户在一个界面内完成文件的浏览、比较和同步操作,极大的提高了工作效率。内置的差异调整和合并修改功能让同步文件夹的工作更加精确和便捷。用户可以针对不同的文件和文件夹进行个性化设置,实现定制化的比较和同步策略。
内容概要:本文介绍了一种基于Simulink的发电机故障暂态仿真模型,旨在深入研究发电机在发生各类短路故障(如单相接地、两相短路接地及两相相间短路)时电压与电流的动态变化特性。该模型精确构建了发电机及其保护系统的电气结构,能够有效模拟故障瞬间的暂态响应过程,全面分析不同接地方式(中性点不接地、经小电阻接地、经消弧线圈接地)对系统电气量的影响。通过仿真获取的电压、电流波形数据,可用于评估电力系统的暂态稳定性、验证继电保护装置的动作逻辑与灵敏性,并为系统控制策略优化及故障诊断提供理论支撑和技术依据。; 适合人群:电气工程及其自动化、电力系统及其相关专业的高校本科生、研究生、科研人员,以及从事电力系统仿真分析、继电保护设计、电网运行维护等工作的工程技术人员。; 使用场景及目标:①用于高校教学与科学研究中对发电机故障机理及暂态过程的可视化分析与深入探讨;②支撑电力系统安全稳定分析、保护定值整定计算、控制策略优化与应急预案制定;③为实际电网故障后的诊断溯源、事故回溯与应急处置决策提供可靠的仿真平台与理论指导。; 阅读建议:建议读者结合MATLAB/Simulink仿真环境进行实践操作,按照文档指导逐步搭建仿真模型,设置不同类型的故障条件进行对比实验,重点观察并分析电压、电流波形的幅值、相位及衰减特性,深入理解其物理成因与系统影响,有条件者可进一步将模型扩展至多机系统以提升研究的工程应用价值。
源码下载地址: https://pan.quark.cn/s/a4b39357ea24 在信息技术行业,特别是智能手机维修和改进的范畴内,“高通9008免拆机救黑砖教程工具”被视为一种通用的处理手段,它主要服务于那些面对设备无法正常运作或处于“黑砖”状态的消费者。这个压缩文件内含针对搭载高通处理器的智能手机的救援指南与实用工具,其核心目标在于协助用户在不进行物理拆解的前提下,成功进入9008模式,进而完成对手机的修复。 我们必须明确理解“高通9008模式”的概念。9008代表了高通芯片的一种下载状态,也称作EDL(eMMC Download Mode)。在该状态下,用户或技术人员能够直接对手机的存储单元进行编程操作、系统升级或固件回载,以此应对软件层面的故障。此类模式一般应用于手机无法正常启动或遭遇严重故障的场合,属于一种较为根本性的修复措施。 “黑砖”状态描述了手机因软件层面的异常而无法开机或完全失去反应的情况,其成因通常涉及系统崩溃、刷机失败、恶意软件入侵等。当常规的恢复措施如强制重启、恢复界面等手段均告无效时,就需要借助9008模式这类特殊通道来实施修复。 小米品牌手机广泛采用了高通处理器,因此当其产品遭遇黑砖问题时,该教程工具显示出极大的实用价值。此压缩文件可能包含以下组成部分: 1. **救砖教程**:提供详尽的流程说明,引导用户如何安全地将设备导入9008模式,以及如何运用相关工具执行固件恢复或刷新操作。 2. **驱动程序**:高通9008模式的有效运行依赖于特定的驱动程序以实现与电脑的通信,压缩包中或许就整合了这些驱动,用户需先行安装它们以便连接手机并开展修复工作。 3. **线刷工具**:诸如MiFlash、QFIL等工具,它们能够支持用户通过...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值