根据前序遍历和中序遍历创建二叉树

根据前序遍历和中序遍历创建二叉树Contents 前言四种遍历树的方法简介简介两种快速获得遍历结果的方法根据前序遍历和后续遍历创建树代码实现四种遍历树的方法的代码前言昨天参加了两场笔试 都考了这个题 第一场是根据 pre

欢迎关注我的微信公众号:MatlabGUI QtCPP等学习记录

根据前序遍历和中序遍历创建二叉树

Contents

前言四种遍历树的方法简介简介两种快速获得遍历结果的方法根据前序遍历和后续遍历创建树代码实现四种遍历树的方法的代码

前言

昨天参加了两场笔试,都考了这个题。第一场是根据pre_order和in_order把创建二叉树的代码写出来,第二场是根据pre_order和in_order把这个二叉树画出来!

当时第一场是C++开发的岗位的笔试,我没做出来,虽然代码写了,但是有Bug一直没改出来(主要还是不熟),他们不让在本地IDE中写,所以没法调试。。。所以第一场笔试我凉了。

第二场是和传感器有关的岗位,虽然这个画出来了,但是其他笔试题有的没学过(没学过那个专业课),有的忘了(比如概率统计)。考的太杂了,感觉也不行。。。

不说废话了,下面讲讲如何根据pre_order和in_order创建二叉树。

四种遍历树的方法简介

简介

首先这里简单介绍一下二叉树的4种遍历方式:

  • 前序遍历(pre_order)
  • 中序遍历(in_order)
  • 后序遍历(post_order)
  • 层序遍历(level_order)

至于这些遍历的代码放在文章的最后。

前序遍历就是先对当前的根节点进行操作,然后到左子节点,再到右子节点!

中序遍历就是先对当前左子节点进行操作,然后到当前根节点,再到右子节点!

后序遍历就是先对当前左子节点进行操作,然后到右子节点,再到当前根节点!

层序遍历就是按照从上到下从左到右的顺序对每个节点进行操作!代码写起来比前三个复杂点,得借助队列,并用迭代的方式来做。

如下图(之前上课做的笔记):

根据前序遍历和中序遍历创建二叉树

两种快速获得遍历结果的方法

另外,介绍两个 可以快速地 根据树的形状 得出 前序、后序、中序 的遍历结果。

法一:

根据前序遍历和中序遍历创建二叉树

法二:

根据前序遍历和中序遍历创建二叉树

根据前序遍历和后续遍历创建树

给你一个数组,用这个数组的值来创建一个树,结果有多种可能:

根据前序遍历和中序遍历创建二叉树

其中n是数组中元素的个数!

但是,如果我们给了两个数组,分别是前序遍历和后续遍历的结果,那么我们就能创建唯一的一个树!

Note:要求数组中的元素不重复,是唯一的!

看过上面对树的那几种遍历方式后,可以发现:

Note:下面的这个过程有点枯燥,我表述地也不太好,可以看后面的图。

  • 前序遍历的第一个元素就是树的根节点;第二个元素是根节点的左子节点,这个左子节点也是后面的根节点;
  • 根节点把中序遍历的数组一分为二,中序遍历的数组中:根节点的左边是左树,根节点的右边是右树
  • 根据前序遍历和中序遍历创建二叉树
  • 所以,我们就对前序遍历的数组进行遍历,当前索引记为pre_i,在每次遍历中,到中序遍历的数组中找这个pre_i对应的值,用这个pre_i把中序遍历的结果一分为二。这样往复下去就能还原树了。

下面我画一下整个流程:

根据前序遍历和中序遍历创建二叉树

大概就是这样,不断地对中序遍历的数组一分为二(根据前序遍历的数组的当前元素进行分割);中序遍历的数组的当前元素就是当前的根节点。

代码实现

先定义树的节点:

template <class T> struct Node{     T val;     Node* left;     Node* right;     explicit Node(T v) : val(v), left(nullptr), right(nullptr){} }; 

根据前序遍历和中序遍历创建树:

/  * @brief 根据前序遍历和中序遍历创建树  * @param[in] pre_vec   前序遍历的数组  * @param[in] in_vec    中序遍历的数组  * @param[in] left_in   中序遍历当前段的左边界  * @param[in] right_in  中序遍历当前段的右边界(超尾)  * @static pre_i        前序遍历的当前的索引  *  * @note 在每一层递归中,当前的 中序遍历 数组段 被分为:[left_in, pre_i), pre_i, [pre_i+1, right_in)  * */ template <class T> Node<T>* CreateTreeR(vector<T>& pre_vec, vector<T>& in_vec, int left_in, int right_in) {     static int pre_i = 0;     if (left_in < right_in)     {         /// 从 前序遍历 的数组中 获取 当前 根节点!         T cur_root_val = pre_vec.at(pre_i);         auto* cur_root = new Node<T>(cur_root_val);         /// 遍历 中序遍历 的数组,找到当前根节点对应的索引         int i = left_in;         while (i < right_in && cur_root_val != in_vec.at(i)) ++i;         /// 下次递归前 pre_i 是需要向后移动一位的         ++pre_i;         /// 一分为二!(注意,i是当前节点的索引哦!)         cur_root->left  = CreateTreeR(pre_vec, in_vec, left_in, i);              /// 左树         cur_root->right = CreateTreeR(pre_vec, in_vec, i+1, right_in);   /// 右树         return cur_root;     }     /// 当分到只剩最后一个元素时就返回空了     return nullptr; } 

测试这段程序

对创建出来的这个树,用四种遍历方法分别遍历一下子,四种遍历的代码在文末。

根据前序遍历和中序遍历创建二叉树

 

根据前序遍历和中序遍历创建二叉树


上面这个是数字的,我现在拿字符串的试试:

根据前序遍历和中序遍历创建二叉树

 

根据前序遍历和中序遍历创建二叉树


四种遍历树的方法的代码

1.层序遍历

/  * @brief 树的层序遍历  * */  template<class T>  void LevelOrder(Node<T>* root, vector<T>& vec) {      /// 如果根节点为空就直接返回      if (!root) return;      /// 定义一个队列放所有可能会成为 "根节点" 的节点(每次循环中都会pop出一个 "根节点" )      queue< Node<T>* > q;      q.push(root);      while (!q.empty())      {          /// 从队列中拿出最前面的根节点          Node<T>* cur_root = q.front();  /// 这个变量在while外面声明更好,不用每次都创建一个新变量。          q.pop();          /// 保存当前 "根节点" 的值          vec.push_back(cur_root->val);          /// 如果左子节点非空就把左子节点放入队列          if (cur_root->left)              q.push(cur_root->left);          /// 如果右子节点非空就把右子节点放入队列          if (cur_root->right)              q.push(cur_root->right);      } } 

2.前序遍历

/  * @brief 树的前序遍历  * */ template<class T> void PreOrder(Node<T>* root, vector<T>& vec) {     if (root)     {         vec.push_back(root->val);         PreOrder(root->left, vec);         PreOrder(root->right, vec);     } } 

3.中序遍历

/  * @brief 树的中序遍历  * */ template<class T> void InOrder(Node<T>* root, vector<T>& vec) {     if (root)     {         InOrder(root->left, vec);         vec.push_back(root->val);         InOrder(root->right, vec);     } } 

4.后序遍历

/  * @brief 树的后序遍历  * */ template<class T> void PostOrder(Node<T>* root, vector<T>& vec) {     if (root)     {         PostOrder(root->left, vec);         PostOrder(root->right, vec);         vec.push_back(root->val);     } } 

根据前序遍历和中序遍历创建二叉树

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232257.html原文链接:https://javaforall.net

(0)
上一篇 2025年10月22日 下午4:01
下一篇 2025年10月22日 下午4:22


相关推荐

  • 2021全国大学生电子设计竞赛–电源–三相逆变(硬件)「建议收藏」

    2021全国大学生电子设计竞赛–电源–三相逆变(硬件)「建议收藏」废话不多说,直接上电路!三相逆变系统的框架如下::那么,降压电路不用多说,网上多得是1、下面说一下逆变驱动电路,也是通篇一律,这里贴上电路图,2、LC滤波器很多人会问我,LC如何选取,还有人在问,为啥我做出来之后发现电感在出声?答:第一个问题,网上可以搜得到,就是一个公式,以基波50HZ进行计算就行。第二个问题,有时候电感明明很大了,仍然出声音,其实那不是电感的问题,由于瓷片电容本身结构的问题,所以就睡导致在高频下的振荡出声,如果换成安规电容或者CBB就会…

    2022年5月25日
    44
  • 安卓网络接口_ap接入点模式

    安卓网络接口_ap接入点模式Android的无线接口层(RIL)提供了Android电话服务(android.telephony)与无线电硬件之间的抽象层。RIL是通讯无关的,提供基于GSM的网络支持。       下图显示了RIL位于Android电话系统架构中的位置:  实线框表示Android部分,虚线框表示合作伙伴所专用的部分RIL包含两个基本部件:       RIL守护进程

    2025年6月6日
    4
  • 京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节「建议收藏」

    京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节「建议收藏」的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里,第京的季节里

    2022年10月3日
    5
  • 万能乘法速算法大全_小学数学加减乘除【速算法】都在这里! 寒假让孩子练一练…

    万能乘法速算法大全_小学数学加减乘除【速算法】都在这里! 寒假让孩子练一练…★需要电子版资料可直接拉至文末查看领取方式哈!小果老师说:很多小朋友的寒假生活已经开启啦!寒假的确可以好好玩一玩,但某种程度上该学习还是的学习一些的!因此,今天小果老师要给大家分享的内容是数学速算法,这些内容掌握以后就几乎不用担心那些简便运算没头绪啦!赶紧来看看然后为孩子收藏起来吧!01加法的神奇速算法一、加大减差法口诀前面加数加上后面加数的整数,减去后面加数与整数的差等于和。例题1376+98…

    2022年6月5日
    37
  • jenkinsfile docker_docker构建自己的镜像

    jenkinsfile docker_docker构建自己的镜像前言之前我们用docker手动安装了jenkins环境,在jenkins中又安装了python3环境和各种安装包,如果我们想要在其他3台机器上安装,又是重复操作,重复劳动,那会显得很low,这里可以

    2022年7月29日
    6
  • Python自动化运维之路-01

    Python自动化运维之路-01python的主要应用python的擅长领域学python有没有前途?python的语言排名语言选择运维会了开发后可以干什么?python的最大优势就是什么都能做。课程概述毕业目标周五

    2022年7月4日
    32

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号