如何根据前序遍历序列和中序遍历序列确定二叉树
二叉树相关的面试题
二叉树相关的面试题一、二叉树面试题常见类型1. 二叉树的概念二叉树就是每个节点最多有两个子树的树结构,这两个子树被分别称为左子树和右子树。
比如说,我们可以想象成一棵家族树,一个爸爸最多有两个孩子,左孩子和右孩子,这就是二叉树的基本概念啦。
2. 二叉树的遍历有前序遍历、中序遍历和后序遍历哦。
前序遍历就是先访问根节点,再访问左子树,最后访问右子树。
就像我们去旅游先到一个景点的大门(根节点),然后去左边的小景点(左子树),最后去右边的小景点(右子树)。
中序遍历是先左子树,再根节点,最后右子树,这就好比先看左边的小景色,再看大门,最后看右边的小景色。
后序遍历是先左子树,再右子树,最后根节点,就像把两边小景色都看完了,最后再看大门整体的感觉。
3. 二叉树的高度计算二叉树的高度就是从根节点到叶节点最长路径上的节点数。
计算的时候要一层一层地去数,从根开始,一直到最深的叶子那里。
4. 二叉树的平衡判断一棵二叉树是平衡二叉树的话,它的左右两个子树的高度差的绝对值不超过1,并且左右子树都是平衡二叉树。
这就像两边的孩子不能长得太不均衡啦,一边特别高,一边特别矮可不行。
5. 二叉树的构建可以根据给定的遍历序列来构建二叉树。
比如说给了前序遍历和中序遍历的序列,我们就可以通过分析先确定根节点,再根据中序遍历确定左右子树,然后逐步构建出二叉树。
这就像是根据一些线索去拼凑出一个完整的图形一样有趣。
二、二叉树面试题实例1. 题目:给定一个二叉树的前序遍历序列为[1, 2, 4, 5, 3, 6, 7],中序遍历序列为[4, 2, 5, 1, 6, 3, 7],构建出这个二叉树。
解答:首先从前序遍历知道根节点是1,然后在中序遍历中找到1,1左边的[4, 2, 5]就是左子树的中序遍历,右边的[6, 3, 7]就是右子树的中序遍历。
再根据前序遍历中左子树节点的顺序[2, 4, 5],可以确定2是左子树的根节点,然后继续这样分析下去就可以构建出二叉树啦。
前序序列中序序列后序序列的规律
标题:前序序列、中序序列和后序序列的规律分析1.概述前序序列、中序序列和后序序列是树的三种遍历方式,它们分别描述了在树结构中节点的访问顺序。
这三种遍历方式具有一定的规律,本文将对这些规律进行分析和总结。
2.前序序列、中序序列和后序序列的定义2.1 前序序列:节点的访问顺序是先访问根节点,然后依次访问左子树和右子树。
2.2 中序序列:节点的访问顺序是先访问左子树,然后访问根节点,最后访问右子树。
2.3 后序序列:节点的访问顺序是先访问左子树,然后访问右子树,最后访问根节点。
3.前序序列、中序序列和后序序列的规律分析3.1 规律一:对于任意一颗树,它的前序序列中的第一个节点必定是根节点。
3.2 规律二:对于任意一颗树,它的中序序列中,根节点的位置将左右子树分割开来。
3.3 规律三:对于任意一颗树,它的后序序列中的最后一个节点必定是根节点。
3.4 规律四:对于同一颗树,其前序序列和后序序列的第二个节点是该树的左子树的根节点。
4.应用举例4.1 求解建立二叉树4.1.1 根据前序序列和中序序列建立二叉树4.1.2 根据中序序列和后序序列建立二叉树4.2 根据前序序列和后序序列求解树的唯一性5.总结前序序列、中序序列和后序序列的规律分析,有助于我们更好地理解树的结构和遍历方式,从而在树的操作中提供了很好的指导。
在实际应用中,可根据这些规律来建立二叉树,求解树的唯一性等问题。
希望通过对这些规律的深入理解,能够更加灵活地应用于相关领域的问题解决中。
6.参考文献[1] 《数据结构与算法分析》,作者:Mark Allen Weiss[2] 《算法导论》,作者:Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein致谢感谢所有对本文撰写提供过帮助的人,包括对数据结构和算法有深入研究的学者们,以及对本文提出宝贵意见和建议的朋友们。
前序遍历中序遍历后序遍历的例题
前序遍历中序遍历后序遍历的例题一、前序遍历、中序遍历和后序遍历的概念和定义前序遍历、中序遍历和后序遍历是二叉树遍历的三种常见方式,它们是根据根节点在遍历序列中的位置进行定义的。
1. 前序遍历:前序遍历是指先访问二叉树的根节点,再依次对左子树和右子树进行前序遍历。
在前序遍历中,根节点总是在最开始的位置。
2. 中序遍历:中序遍历是指先遍历二叉树的左子树,然后访问根节点,最后遍历右子树。
在中序遍历中,根节点总是在左子树和右子树之间。
3. 后序遍历:后序遍历是指先遍历二叉树的左子树和右子树,然后访问根节点。
在后序遍历中,根节点总是在最后的位置。
二、前序遍历、中序遍历和后序遍历的应用前序遍历、中序遍历和后序遍历在二叉树的构建、搜索和遍历等方面起着重要的作用。
对于一个给定的二叉树,我们可以根据前序遍历和中序遍历来唯一确定它的结构。
类似地,我们也可以根据中序遍历和后序遍历来唯一确定二叉树的结构。
这个特性在解析和构建二叉树的过程中非常有用。
假设我们已知一个二叉树的前序遍历和中序遍历序列,我们可以根据这两个序列来构建出这个二叉树。
具体方法是:1. 从前序遍历序列中找到根节点,根节点是第一个元素;2. 在中序遍历序列中找到根节点的位置,根节点左侧的元素是左子树的节点,右侧的元素是右子树的节点;3. 根据上一步得到的左子树和右子树的节点,在前序遍历序列中找到对应的部分,分别对左子树和右子树进行递归构建。
这个方法可以保证我们得到的二叉树是原始二叉树的一个唯一构建。
同样地,我们也可以根据中序遍历和后序遍历来构建二叉树的过程类似。
三、实例分析:前序遍历中序遍历后序遍历的例题让我们通过一个具体的例题来深入理解前序遍历、中序遍历和后序遍历的应用。
假设我们有以下一棵二叉树:```/ \2 3/ \ / \4 5 6 7```给定该二叉树的前序遍历序列为1, 2, 4, 5, 3, 6, 7,中序遍历序列为4, 2, 5, 1, 6, 3, 7,后序遍历序列为4, 5, 2, 6, 7, 3, 1。
形考作业三及答案
形考作业三及答案本部分作业覆盖教材第6-7章的内容)一、单项选择题1.假定一棵二叉树中,双分支结点数为15,单分支结点数为30,则叶子结点数为()。
A.15 B.16 C.17 D.472.二叉树第k层上最多有()个结点。
A.2k B.2k-1C.2k-1 D.2k-13.二叉树的深度为k,则二叉树最多有()个结点。
A.2k B.2k-1C.2k-1 D.2k-14. 设某一二叉树先序遍历为abdec,中序遍历为dbeac,则该二叉树后序遍历的顺序是()。
A.abdec B.debac C.debca D.abedc5.将含有150个结点的完全二叉树从根这一层开始,每一层从左到右依次对结点进行编号,根结点的编号为1,则编号为69的结点的双亲结点的编号为()。
A.33 B.34 C.35 D.366.如果将给定的一组数据作为叶子数值,所构造出的二叉树的带权路径长度最小,则该树称为()。
A.哈夫曼树 B.平衡二叉树C.二叉树 D.完全二叉树7.下列有关二叉树的说法正确的是()。
A.二叉树中度为0的结点的个数等于度为2的结点的个数加1B.二叉树中结点个数必大于0C.完全二叉树中,任何一个结点的度,或者为0或者为2D.二叉树的度是28.在一棵度为3的树中,度为3的结点个数为2,度为2的结点个数为1,则度为0的结点个数为()。
A.4 B.5 C.6 D.79.在一棵度具有5层的满二叉树中结点总数为()。
A.31 B.32 C.33 D.1610. 利用n个值作为叶结点的权生成的哈夫曼树中共包含有( )个结点。
A. nB. n+1C. 2*nD. 2*n-111. 利用3、6、8、12这四个值作为叶子结点的权,生成一棵哈夫曼树,该树中所有叶子的最长带权路径长度为( )。
A. 18B. 16C. 12D. 3012.在一棵树中,()没有前驱结点。
A.分支结点 B.叶结点 C.树根结点 D.空结点13.在一棵二叉树中,若编号为i的结点存在右孩子,则右孩子的顺序编号为()。
二叉树前中后序遍历做题技巧
二叉树前中后序遍历做题技巧在计算机科学中,二叉树是一种重要的数据结构,而前序、中序和后序遍历则是二叉树遍历的三种主要方式。
下面将分别对这三种遍历方式进行解析,并提供一些解题技巧。
1.理解遍历顺序前序遍历顺序是:根节点->左子树->右子树中序遍历顺序是:左子树->根节点->右子树后序遍历顺序是:左子树->右子树->根节点理解每种遍历顺序是解题的基础。
2.使用递归或迭代二叉树的遍历可以通过递归或迭代实现。
在递归中,每个节点的处理函数会调用其左右子节点的处理函数。
在迭代中,可以使用栈来模拟递归过程。
3.辨析指针指向在递归或迭代中,需要正确处理指针的指向。
在递归中,通常使用全局变量或函数参数传递指针。
在迭代中,需要使用栈或其他数据结构保存指针。
4.学会断点续传在处理大规模数据时,为了避免内存溢出,可以采用断点续传的方式。
即在遍历过程中,将中间结果保存在文件中,下次遍历时从文件中读取上一次的结果,继续遍历。
5.识别循环和终止条件在遍历二叉树时,要识别是否存在循环,并确定终止条件。
循环可以通过深度优先搜索(DFS)或广度优先搜索(BFS)避免。
终止条件通常为达到叶子节点或达到某个深度限制。
6.考虑边界情况在处理二叉树遍历问题时,要考虑边界情况。
例如,对于空二叉树,需要进行特殊处理。
又如,在处理二叉搜索树时,需要考虑节点值的最小和最大边界。
7.优化空间使用在遍历二叉树时,需要优化空间使用。
例如,可以使用in-place排序来避免额外的空间开销。
此外,可以使用懒加载技术来延迟加载子节点,从而减少内存占用。
8.验证答案正确性最后,验证答案的正确性是至关重要的。
可以通过检查输出是否符合预期、是否满足题目的限制条件等方法来验证答案的正确性。
如果可能的话,也可以使用自动化测试工具进行验证。
锦州医科大学医疗学院计算机考试期末
锦州医科大学医疗学院计算机考试期末一、单项选择题(总题数:27,分数:54.00)1.单项选择题1-40小题。
下列每题给出的四个选项中,只有一个选项是最符合题目要求的。
(分数:2.00)__________________________________________________________________ ________________________解析:2.先序序列为a,b,c,d的不同二叉树的个数是_______。
(分数:2.00)A.13B.14 √C.15D.16解析:解析:根据二叉树前序遍历和中序遍历的递归算法中递归工作栈的状态变化得出:前序序列和中序序列的关系相当于以前序序列为入栈次序,以中序序列为出栈次序。
因为前序序列和中序序列可以唯一地确定一棵二叉树,所以题意相当于“以序列a,b,c,d为入栈次序,则出栈序列的个数为?”,对于n个n不同元素进栈,出栈序列的个数为C =14。
2n3.假设栈初始为空,将中缀表达式a/b+(c*d-e*f)/g转换为等价的后缀表达式的过程中,当扫描到f时,栈中的元素依次是_______。
(分数:2.00)A.+(*-B.+(-* √C./+(*-*D./+-*解析:解析:将中缀表达式转换为后缀表达式的算法思想如下:从左向右开始扫描中缀表达式;遇到数字时,加入后缀表达式;遇到运算符时:a.若为‘(’,入栈;b.若为‘)’,则依次把栈中的的运算符加入后缀表达式中,直到出现‘(’,从栈中删除‘(’;c.若为除括号外的其他运算符,当其优先级高于除‘(’以外的栈顶运算符时,直接入栈。
否则从栈顶开始,依次弹出比当前处理的运算符优先级高和优先级相等的运算符,直到一个比它优先级低的或者遇到了一个左括号为止。
当扫描的中缀表达式结束时,栈中的所有运算符依次出栈加入后缀表达式。
4.在一棵度为4的树T中,若有20个度为4的结点,10个度为3的结点,1个度为2的结点,10个度为1的结点,则树T的叶结点个数是_______。
二叉树的遍历及其应用
0引言
所谓遍历,是指沿着某条搜索路线,依次对树中每个结点均做一次 且仅做一次访问。访问结点所做的操作依赖于具体的应用问题。 遍历 在二叉树上最重要的运算之一,是二叉树上进行其它运算之基础。二叉 树作为一种重要的数据结构是工农业应用与开发的重要工具。遍历是二 叉树算法设计中经典且永恒的话题。经典的算法大多采用递归搜索。递 归算法具有简练、清晰等优点,但因其执行过程涉及到大量的堆栈使 用,难于应用到一些严格限制堆栈使用的系统,也无法应用到一些不支 持递归的语言环境[9]。
由先序序列和中序序列来还原二叉树的过程算法思想[7]: (1)若二叉树空,返回空; (2)若不空,取先序序列第一个元素,建立根节点; (3)在中序序列中查找根节点,以此来确定左右子树的先序序列和中 序序列; (4)递归调用自己,建左子树; (5)递归调用自己,建右子树。
4二叉树的遍历的应用
根据二叉树的遍历算法, 可得出如下规律: 规律1: 前序序列遍历第一个为根结点, 后序遍历的最后一个结点为 根结点。 规律2: 前序序列遍历最后一个为根结点右子树的最右叶子结点, 中 序遍历的最后一个结点为根结点右子树的最右叶子结点。 规律3: 中序序列遍历第一个结点为根结点左子树的最左叶子结点,
1遍历二叉树的概念
所谓遍历二叉树,就是遵从某种次序,访问二叉树中的所有结点, 使得每个结点仅被访问一次。这里提到的“访问”是指对结点施行某种 操作,操作可以是输出结点信息,修改结点的数据值等,但要求这种访
问不破坏它原来的数据结构。在本文中,我们规定访问是输出结点信息 data,且以二叉链表作为二叉树的存贮结构。由于二叉树是一种非线性 结构,每个结点可能有一个以上的直接后继,因此,必须规定遍历的规 则,并按此规则遍历二叉树,最后得到二叉树所有结点的一个线性序 列[1]。
已知一棵二叉树的前序遍历结果为abcdefg,中序遍历结果为bcaedgf,则后序遍历的结果
已知一棵二叉树的前序遍历结果为abcdefg,中序遍历结果为bcaedgf,则后序遍历的结果前序遍历结果为 abcdefg,中序遍历结果为 bcaedgf,则后序遍历的结果为 axial degree,则集合中每个边所对应的树是一个树。
因此,其树前序遍历过程中每一个步骤都是错误的。
这是在给定一个树后序遍历(abcdefg)后得到的结果。
所以,对于任意一点 A与 B均为2次遍历结果之差。
这是一个中序遍历的例子。
但是对于已经遍历x,则树前序和中序都是先遍历出来,在这个节点为x且是奇数,则表示该树为 abcdefg树是1个二叉树。
因此后序遍历的结果与本节无关。
由于其仅有数行且没有边,所以一般只需要将前序遍历结果保存在一个指定的位置即可。
但是如果不考虑遍历过程中出现一个参数,就会出现以下问题:若该参数为负数怎么办?如何解决:首先如果这个变量不存在,那么所有状态变量都是0,则该根因函数;如果该参数为“0”则对数据进行唯一遍历即可得到全部结果。
若我们有两个以上的二叉树同时生长且不影响其结果的话,那么这样两个数据都要全部遍历一遍之后得到一个概率为100%的集合。
为了达到这个目的需要构造两个不同的序列:一个序列可以是非0;另一个序列也是1或者是2种不同形式。
(如果存在一种序列)这种算法可以用于处理二次概率论中常用的一些问题。
1.树的基本结构根据概率论,每个元素有 n种状态变量,包括状态变量(比如:“状态变量”的含义为状态变量与状态值之间的关系),可以用如下公式描述:其中 b是状态变量中的1, n是一个随机数; b为状态变量的值为 k; k为一个整数。
其中 N是 n维树体的数列; N是每个边所对应的集合; n 是在一个集合中所对应的边数目。
每个边都是固定的值;所以,每个边代表树2中所有边都是1。
因此每一个节点对任意 b都是唯一的。
由于 k是1个实数,所以在给定条件下该集合是2×2倍数,也就是说从 b开始计算,每一个元素是其前序遍历得到的结果是所有 b中都是1。
二叉树遍历(前中后序遍历,三种方式)
⼆叉树遍历(前中后序遍历,三种⽅式)⽬录刷题中碰到⼆叉树的遍历,就查找了⼆叉树遍历的⼏种思路,在此做个总结。
对应的LeetCode题⽬如下:,,,接下来以前序遍历来说明三种解法的思想,后⾯中序和后续直接给出代码。
⾸先定义⼆叉树的数据结构如下://Definition for a binary tree node.struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}};前序遍历,顺序是“根-左-右”。
使⽤递归实现:递归的思想很简单就是我们每次访问根节点后就递归访问其左节点,左节点访问结束后再递归的访问右节点。
代码如下:class Solution {public:vector<int> preorderTraversal(TreeNode* root) {if(root == NULL) return {};vector<int> res;helper(root,res);return res;}void helper(TreeNode *root, vector<int> &res){res.push_back(root->val);if(root->left) helper(root->left, res);if(root->right) helper(root->right, res);}};使⽤辅助栈迭代实现:算法为:先把根节点push到辅助栈中,然后循环检测栈是否为空,若不空,则取出栈顶元素,保存值到vector中,之后由于需要想访问左⼦节点,所以我们在将根节点的⼦节点⼊栈时要先经右节点⼊栈,再将左节点⼊栈,这样出栈时就会先判断左⼦节点。
代码如下:class Solution {public:vector<int> preorderTraversal(TreeNode* root) {if(root == NULL) return {};vector<int> res;stack<TreeNode*> st;st.push(root);while(!st.empty()){//将根节点出栈放⼊结果集中TreeNode *t = st.top();st.pop();res.push_back(t->val);//先⼊栈右节点,后左节点if(t->right) st.push(t->right);if(t->left) st.push(t->left);}return res;}};Morris Traversal⽅法具体的详细解释可以参考如下链接:这种解法可以实现O(N)的时间复杂度和O(1)的空间复杂度。
利用遍历序列还原二叉树算法的研究与实现
whl j+ ! pe i i (( m) (r+) e n = . )
m ++ :
i( fm== 、 k
p >i h l = - c id NULL;
es le
whl i+ l p s j) i (( m) (ot ) e n = +
m ++ :
p>e i = ritt epei, l+ kkm一) - l l penor (r, i , m-, hd e n+ i , 1
B r No e pe tt ec a pe 】 c a t e d ri or (h r r[ , hr e n e
树 。根 据遍 历 序 列 还 原 一 棵 二义 树 的基 本过 为 :先还 原根 结 点 ,再还 原左子 树和 右子 树 ,可
以 由前 序或 后序 序 列确 定根 结 点 , 然后 再利 川 中
,
i( fm== k
p >lh l = - c id NULL;
i( : 1 f m =)
p >r h l = - c i NUL ; d L
es le
es le
p>c i = ot tt ep si, -l l p snor (o tn hd i e ,
i+ k Ikm- ) , m— —,, I; i i( f m== ) h
在 前序 序 列 中 的 第 一个 结 点 即为 二义 树 的
根 结点 , 位置 为 i。 中序序 p 中 找到根 结 点 其 在 - 0 位置 ( , m) 以确定左 右 子树上 的结点 ( 左 边 为 m 左子 树 结点 ,右边 为 右子树 结 点 ) 。然 后再 到前
后 右子 树 ,最 后根 结 点 。 由前 序 遍 历 1 遍 历序 列 或 者 由中序 遍 中序
由前序跟中序遍历序求后序遍历序的设计与实现
(中文)由前序跟中序遍历序求后序遍历序的设计与实现(英文)The design and implementation of getting postorder traversal according to preorderand inorder traversal of a binary tree蔡智聪摘要:树的遍历问题在应用开发过程中是一个很经典且常遇到的问题,在实际工程中,经常可能需要进行某种遍历充的求解。
本文介绍如何由一棵二叉树的前序遍历序和中序遍历序来后序遍历序的设计思路与具体C++实现。
首先根据前序遍历序和中序遍历序来建立(还原)出二叉树的原型,文中详细介绍了建立(还原)树的算法及原理。
然后再用后后序遍历算法求后序遍历序(一串字符串序列)。
关键字:二叉树前序遍历序中序遍历序后序遍历序Binary –Tree ,Preorder traversal, inorder traversal, postorder traversal正文:几个术语的介绍:二叉树:在计算机科学中,二叉树是每个结点最多有两个子树的有序树。
通常子树的根被称作“左子树”(left subtree)和“右子树”(right subtree)。
前序遍历序:在对一个树进行前序遍历而得到的一个访问结点的序列。
遍历的顺序是:先父结点,然后左子树,然后右子树。
中序遍历序:在对一个树进行中序遍历而得到的一个访问结点的序列。
遍历的顺序是:先左子树,然后父结点,然后右子树。
前序遍历序:在对一个树进行前序遍历而得到的一个访问结点的序列。
遍历的顺序是:先左子树,然后右子树,然后父结点。
引言:树的遍历问题在应用开发过程中是一个很经典且常遇到的问题,在实际工程中,经常可能需要进行某种遍历充的求解。
为了描述和实现的简化,本文中以二叉树来代替为例,并将二叉树的结点抽象成一个字符来代替,在实现运用中可以自己加以灵活变通。
问题的引出:那么对于一棵给定的二叉树,如何根据前序遍历序和中序遍历序来求出后序遍历序呢?如图A:这样的一棵树的前序遍历序为:ABDGHCEIFJ中序遍历序为:GDHBAEICFJ那么如何求出后序遍历序(GHDBIEJFCA)呢?算法原理及分析:1.先建立还原二叉树。
证明:由一棵二叉树的先序序列和中序序列可唯一确定这棵二叉树
因为知道先序遍历后,第一个根是唯一确定的.然后在中序遍历里这个根将它分为两个部分,第一个根的两棵子树的根也会唯一确定,依次此类推,所有子树的根都唯一确定,二叉树就是唯一的.解题步骤1.由先序序列确定根结点(就是第一个字母了)2.按根结点把中序序列分为两段,前面的是左子树,后面的是右子树后面的步骤就基本是前面两步的重复注意先序序列和中序序列的概念这题目就很容易的搞定#include<stdio.h>#include<stdlib.h>typedef char TElemType;//Status是函数的类型,其值是函数结果状态码typedef int status;//函数结果状态代码#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1#define OVERFLOW -2int w=0;#define Link 0#define Thread 1typedef struct BiThrNode{TElemType data;struct BiThrNode *lchild,*rchild; //左右孩子指针 int LTag,RTag;}BiThrNode,*BiThrTree;//构造二叉链表表示的二叉树status createbitree(BiThrTree &T){char ch;scanf("%c",&ch);if(ch=='$') T=NULL;else{if(!(T=(BiThrNode*)malloc(sizeof(BiThrNode))))exit(OVERFLOW);T->data =ch;T->LTag=Link;T->RTag=Link;createbitree(T->lchild);createbitree(T->rchild);}return OK;}void InThreading(BiThrTree &p,BiThrTree &pre) { // 算法6.7 //BiThrTree pre;if (p){InThreading(p->lchild,pre); // 左子树线索化if (!p->lchild) // 建前驱线索{ p->LTag = Thread; p->lchild = pre; }if (!pre->rchild) // 建后继线索{ pre->RTag = Thread; pre->rchild = p; }pre = p; // 保持pre指向p的前驱InThreading(p->rchild,pre); // 右子树线索化}} // InThreading//输出元素status visit(TElemType e){printf("%c",e);return OK;}status InOrderTraverse_Thr(BiThrTree T, status (*Visit)(TElemType)) {// 中序遍历二叉树T,并将其中序线索化,Thrt指向头结点。
前序序列和后续序列确定二叉树
前序序列和后续序列确定⼆叉树⼆叉树:已知前序与后序建树那么我们换⼀种思考⽅式,我们先来看看先序与后序序列的排布规律。
以下⾯这棵树来举例:其先序序列为: 1 2 3 4 6 7 5后序序列为:2 6 7 4 5 3 1⾸先我们要知道:先序序列遍历顺序是:根结点-左⼦树-右⼦树后序序列遍历顺序是:左⼦树-右⼦树-根结点很明显,我们可以看出结点在先、后序列中的排布有以下这些特征:【1】、在先序序列中,根结点在⼦树中的结点前⾯,在后序序列中,根结点在⼦树中的结点后⾯。
【2】、以任⼀节点为根结点时,其⼦树在先序后序序列中排布都是先左⼦树后右⼦树,⽽根结点排在最后。
那么,反过来思考,已知这个先序与后序序列所确定的树是唯⼀的吗?进⼀步推⼴:怎么通过先序与后序序列判断是否存在唯⼀的树呢?现在,我们来⼀步步分析已知先序与后序的建树过程:①、根据特征【1】可知:根结点为先序序列第⼀个节点以及后序序列最后⼀个结点,因此根结点为1。
②、先序序列中第⼆个结点为2,其在后序序列中的位置是第⼀个,那么根据特征【2】我们可以知道结点2是没有⼦树的,⽽且结点2要么在根结点的左⼦树,要么在右⼦树。
假设结点2在右⼦树,那么由特征【2】可知根结点1没有左⼦树,⽽且先序序列中结点2后⾯的结点全部为结点2的⼦树上的结点。
再看后序序列,由特征【2】可知,结点2后⾯的结点不可能是其⼦树上的结点。
因此,假设显然与已知⽭盾。
这样,我们⼜知道结点2是结点1的左孩⼦,且结点2没有⼦结点。
③、先序序列第三个位置上的结点为3,该结点在后序序列中排倒数第⼆个。
由②可知,结点3必然是根结点1的右孩⼦。
④、先序序列第四个位置上的结点为4,该结点在后序序列中排第四个。
因为结点4在先序序列中排在结点3后⾯,⼜因为结点3是根结点1的右孩⼦,所以结点4只可能在结点3的⼦树上。
结点3的⼦树可能出现的情况是:只有左⼦树,只有右⼦树,左右⼦树都有。
因为在后序序列中,结点4左边是结点6、7,右边是结点5。
从前序和中序遍历构造二叉树算法
+1); //建右子树
return t:
l (二 )算法1的复杂性分析
设 r(/7)是从长为n的前序和 中序遍 历序列构造二又 树的H ̄1 ̄1复杂度,设分 划节点在 中序遍历序列 的第k个 节点 ,则 有 如下 递 推公 式
fro)=1
(,1)=r(k一1)+ (,l一七)+,l 最坏情况下,时间复杂度是 0(/7 ),空间复杂度是 D(力);平均情况下,时间复杂度是0(nlogn),空间复杂 度 是 0(1ogn)。
时间复 杂度是O(n )的主要原因是 ,在每次调用递归函 数 的时候 ,根 据在前序遍历得 到的根廿|点的关 键 字的 值 ,需要一 个循环来在中序遍历序列中 “定位”分 划节 点,这就是造成算法慢 的症结所在。如果要得到一个更 快 的算法 ,很 自然要考虑能否减少这个 “定位 ”所 花的 时 间开 销 。
t_->Leff=Build(InFrom,i-1,PreFrom+1);//建左 子 树
t->Right=Build(i+l,InTo,PreFrom +i—InFrom
+1);∥建右子树
2012年 。第 2期 投稿 邮箱 hnfc@21cn.net J 61
实务 ·软件服务
栏 目编 辑 梁 丽 雯 E—mail:liven 01@163 COrn
re[Urn t:
} 2.算 法2的复杂 性 分析 设 )是从长为n的前序和中序遍历序列构造二叉 树 的时间复杂度 ,设分划节 在中序遍历序列的第k个 节 ,则有如下递推公式
基于遍历序列重构二叉结构树的分析
2 遍历序 列重构 二叉树 的条件分析
对 于一 棵 非 空 二 叉树 ,它 的先 序 遍 历序 列 、 中
序遍历序列或后序遍历序列有可能相 同,但三种遍 历 序 列不 可 能都 相 同 _ 另外 ,每 棵二 叉 树 的先 序遍 历 序列 、中序遍历序列和后序遍历序列都是唯一的. 那 么对 于 一个 给定 的二 叉树 ,要 得 到它 的遍历 序 列 很 容 易得 到 ,反 过 来 , 由遍 历 序 列 能否 确 定一 棵 二 叉 树 吗 ?是 否唯 一 ?显 然 ,由一 种遍 历 序 列不 能唯 一 确 定 一棵 二 叉树 . 本 文将 对 三种 遍历 序 列 的组 合唯 一 确 定二叉 树 进行讨 论 . 定理1 : 给 定 一 棵 二 叉 树 的先 序 序 列 和 中 序 序 列 ,可 唯一 确定一 棵 二叉树 . 证 明 设二 叉树 结点 的个 数为n ( n ≥0 ) . 当n = O 时 ,一 棵空 二叉树 的中序序 列 和先序 序列 都 为 空 ,可 以唯一确 定该 二叉 树 ,命 题成 立. 设 当0 n≤k , k≥0 时命 题都成 立 ,下 面证 明 当 = 足 + 1 时命 题 也 成 立 . 设一 棵 二 叉 树 的 中序 序 列 和先序序列分别 为a , ,a : ,…,a k + l 和b , ,b ,… , b …. 根 据二 叉 树 的先 序 序 列定 义 ,b , 为根 ,b 。 在a 。 , a 2 ,…,a 中 出现 一 次 ,设 a - - b ( J i : + 1 ) . 根据 二 叉树 中序序列定义 ,若i = l ,则左子树的中序序列为 空 ,且左 子 树 的先 序序 列 也为 空 ,若2 i ≤k + 1 ,则 a ,a ,…,a H为左 子树 的中序序 列 ,将a , ,a 2 ,…, a 中的 所 有结 点 按 其 在b ,b : ,…,b ㈨中 的相 对 次 序排 列成 b p l ,b p 2 … . ,b p . - 1 ( 2 ≤ P l 蔓 7 : … P “ k + 1 ) , 易知 ,b p l 'b p 2 '…,b p i - i 唯一 ,为左子树的先序序 列 ,根据 上 面 归 纳法 的假 设 ,由于 左 子树 的结 点 的 个数在O  ̄ i i ] l k 之间 ,则由左子树的中序序列和先序序 列可 以唯一确定该左子树 ,同理 ,由右子树 的中序 序列和先序序列也可以唯一确定该右子树. 因此 ,由 棵二叉树 的中序序列a 。 ,a : ,…,a ㈧和先序序列 b ,b ,…,b k + l 可 以唯一确定该二叉树 ,即当 时命
二叉树的先序,中序,后序遍历代码
二叉树的先序,中序,后序遍历代码一、二叉树的先序、中序和后序遍历1、先序遍历先序遍历是根节点、左子树、右子树的顺序访问二叉树的一种遍历方法。
在先序遍历中,先访问根节点,然后递归访问左子树,最后递归访问右子树。
具体的代码如下:(1)//先序遍历法PreOrder(Tree T){if(T!=NULL){Visit(T);//访问根节点PreOrder(T->Left);//遍历左子树PreOrder(T->Right);//遍历右子树}}2、中序遍历中序遍历是左子树、根节点、右子树的顺序访问二叉树的一种遍历方法。
在中序遍历中,先递归访问左子树,然后访问根节点,最后递归访问右子树。
具体的代码如下:(2)//中序遍历法InOrder(Tree T){if(T!=NULL){InOrder(T->Left);//遍历左子树Visit(T);//访问根节点InOrder(T->Right);//遍历右子树}}3、后序遍历后序遍历是左子树、右子树、根节点的顺序访问二叉树的一种遍历方法。
在后序遍历中,先递归访问左子树,然后递归访问右子树,最后访问根节点。
具体的代码如下:(3)//后序遍历法PostOrder(Tree T){if(T!=NULL){PostOrder(T->Left);//遍历左子树PostOrder(T->Right);//遍历右子树Visit(T);//访问根节点}}二、先序、中序和后序遍历的应用(1)构造二叉树先序序列和中序序列是完全可以解决构造出一颗二叉树的,必要的条件是中序和先序的元素的个数必须相同。
后序序列无法实现这一点,只能确定根节点的位置。
(2)深度优先搜索深度优先搜索是一种图遍历算法,它使用栈来帮助用户访问一棵树,也就是深度优先算法。
先序遍历是先从根节点访问,中序遍历是在访问左子树后再访问根节点,而后序遍历是在访问右子树后再访问根节点。
(3)计算二叉树深度根据先序遍历和后序遍历可以知道二叉树的深度。
前序遍历和中序遍历唯一确定一颗二叉树
前序遍历和中序遍历唯⼀确定⼀颗⼆叉树---恢复内容开始---问题描述如果给出了遍历⼆叉树的前序序列和中序序列,则可以构造出唯⼀的⼀颗⼆叉树。
基本要求已知⼀棵⼆叉树的前序序列和中序序列,试设计完成下列任务的⼀个算法:(1).构造⼀颗⼆叉树(2).证明构造正确(即分拨⼉以前序和中序遍历该树,将得到的结果与给出的序列进⾏⽐较)(3).对该⼆叉树进⾏后序遍历,输出后序遍历序列(4).⽤凹⼊法输出该⼆叉树测试数据前序序列为ABDEGCFHIJ,中序序列为DBGEAHFIJC代码思路1.确定树的根节点,树根是当前树中所有元素在前序遍历中最先出现的元素。
2.求解树的⼦树,找出根节点在中序遍历中的位置,根左边的所有元素就是左⼦树,根右边的所有元素就是右⼦树。
若根节点左边或右边为空,则该⽅向⼦树为空;若根节点左边和右边都为空,则根节点已经为叶⼦节点。
3.递归求解树,将左⼦树和右⼦树分别看成⼀棵⼆叉树,重复1、2、3步,直到所有的节点完成定位。
源代码/*1.确定树的根节点,树根是当前树中所有元素在前序遍历中最先出现的元素。
2.求解树的⼦树,找出根节点在中序遍历中的位置,根左边的所有元素就是左⼦树,根右边的所有元素就是右⼦树。
若根节点左边或右边为空,则该⽅向⼦树为空;若根节点左边和右边都为空,则根节点已经为叶⼦节点。
3.递归求解树,将左⼦树和右⼦树分别看成⼀棵⼆叉树,重复1、2、3步,直到所有的节点完成定位。
*/#include<iostream>#include<algorithm>#include<string>#include<cstring>using namespace std;const int maxint = 10000;char ch1[maxint], ch2[maxint]; //前序序列,中序序列int length; //⼆叉树结点的个数struct tree {char name;struct tree *leftchild;struct tree *rightchild;};//访问函数void vis(char name) {cout << name;}//初始化void init(struct tree **root){*root = (struct tree *)malloc(sizeof(struct tree));(*root)->leftchild = NULL;(*root)->rightchild = NULL;}//创建左⼦树struct tree *build_ltree(struct tree *h,char name) {struct tree *p, *t;if (h == NULL) return NULL;t = h->leftchild;p= (struct tree*)malloc(sizeof(struct tree));p->name = name;p->leftchild = t;p->rightchild = NULL;h->leftchild = p;return h->leftchild;}//创建右⼦树struct tree *build_rtree(struct tree *h, char name) {struct tree *p, *t;if (h == NULL) return NULL;t = h->rightchild;p = (struct tree*)malloc(sizeof(struct tree));p->name = name;p->leftchild = NULL;p->rightchild = t;h->rightchild = p;return h->rightchild;}void print_tree(struct tree *t, int n) {if (t == NULL) return;print_tree(t->rightchild, n + 1);for (int i = 0; i < n - 1; i++) cout << "";if (n > 0) {cout<<"***";cout << t->name << endl;}print_tree(t->leftchild, n + 1);}//前序遍历void preorder(struct tree *t, void vis(char name)) {if (t != NULL) {vis(t->name);preorder(t->leftchild, vis);preorder(t->rightchild, vis);}}//中序遍历void inorder(struct tree *t, void vis(char name)) {if (t != NULL) {inorder(t->leftchild, vis);vis(t->name);inorder(t->rightchild, vis);}}//后序遍历void postorder(struct tree *t, void vis(char name)) {if (t != NULL) {postorder(t->leftchild, vis);postorder(t->rightchild, vis);vis(t->name);}}//寻找对应中序序列中和前序序列相对应的结点的位置int bfs(char ch[],char name) {int i(0);while (ch[i] != name) ++i;return i;}//找到左⼦树的位置int seek_left(int flag[], int t){int temp;temp = t;while (flag[temp] != 1 && temp >= 0)temp--;if (flag[temp] == 1)return temp;else return -1;}//找到右⼦树的位置int seek_right(int flag[], int t){int temp;temp = t;while (flag[temp] != 1 && temp <= 10000)temp++;if (flag[temp] == 1)return temp;else return -1;}int main() {while (1) {cout << " ***************唯⼀确定⼀颗⼆叉树***************" << endl;cout << " * *" << endl;cout << " * 给定前序序列和中序序列唯⼀确定⼀颗⼆叉树 *" << endl; cout << " * *" << endl;cout << " ************************************************" << endl;struct tree *root; //定义根节点init(&root); //创建根节点struct tree *node_tree[maxint]; //⼆叉树中的结点int flag[maxint]; //标记数组int left, right;memset(flag, 0, sizeof flag); //标记数组全部赋值为0cout << "请输⼊前序序列:";cin >> ch1;cout << "请输⼊中序序列:";cin >> ch2;length = strlen(ch1);char node; //前序序列中的结点int num; //中序序列中对应前序序列结点的位置for (int i = 0; i < length; ++i) {node = ch1[i];num = bfs(ch2, node);left = seek_left(flag, num); //找到左⼦树位置right = seek_right(flag, num); //找到右⼦树位置if (left == -1 && right == -1) { //第⼀次的时候肯定会执⾏这个条件后⾯的语句 node_tree[num] = build_ltree(root, node);flag[num] = 1;}else if (left != -1 && node_tree[left]->rightchild == NULL) {node_tree[num] = build_rtree(node_tree[left], node);flag[num] = 1;}else if (right != -1 && node_tree[right]->leftchild == NULL) {node_tree[num] = build_ltree(node_tree[right], node);}}cout << "此⼆叉树的结构是:" << endl << endl;print_tree(root, 0);cout << "此⼆叉树的前序序列为:";preorder(root->leftchild, vis);cout << endl;cout << "此⼆叉树的中序序列为:";inorder(root->leftchild, vis);cout << endl;cout << "此⼆叉树的后序序列为:";postorder(root->leftchild, vis);cout << endl << endl << endl;}return0;}效果图总结断更⼀个⽉后,重新写博。
【题10】根据根据前、中序遍历求后序遍历--试题解析
【题10】根据根据前、中序遍历求后序遍历约定一棵二叉树的前序遍历和中序遍历序列,用你熟悉的程序设计语言生成该二叉树,并将其后序遍历打印出来。
为便于编程,二叉树的结点用单个大写英文字母表示,且结点互不重复。
比如,输入前序遍历序列为DBACPMZX,中序遍历序列为ABCDMPXZ,应生成的二叉树结构如图6.1.13所示:图6.1.13应输出的后序遍历序列为ACBMXZPD注意:你的程序应能鉴别任何的错误输入。
题解1鉴别错误输入设predstr—前序串;s1—前序串的字符集;midstr—中序串;s2—中序串的字符集;predstr串与midstr串必须同时满足下述三个条件方可对应同一棵二叉树:1.predstr串与midstr串的长度相等;2.两串的字符为{’A’‥’Z’}的子集且各不相同;3.在predstr串中的字符必须在midstr串出现;判别输入合法性的过程由布尔函数correct完成。
若输入合法(即predstr串与midstr串可对应同一棵二叉树),则返回true;否则返回false。
fuction correct:boolean;begincorrect←false;if length(predstr)=length(minstr) {若两序列的长度相同}then begins1←[];{前序串的字符集初始化}for i←1 to length(predstr) do {分析前序串的每一个字符}if (predstr[i]∈s1)or(predstr[i]∉[’A’‥’Z’])then exit {若前序串中字符重复或出现非法字符,则返回false}else s1←s1+[predstr[i]];{否则当前字符进入前序串的字符集}s2←[];{中序串的字符集初始化}for i←1 to length(midstr) doif (midstr[i]∉s1)or(midstr[i]∈s2)then exit {若中序串的当前字符非前序串字符或者为重复字符,则返回false}else s2←s2+[midstr[i]];{否则当前字符进入中序串的字符集}correct←true;{返回输入合法标志}end;{then}end;{correct}2构造两个线性序列对应的二叉树若给出一棵二叉树的前序遍历和中序遍历,那么这两个线性序列可以唯一对应一棵二叉树。
二叉树的遍历
T->rchild= CreatBiTree(); /*构造右子树*/ 扩展先序遍历序列
}
2021/2/21
return (T) ;}
A B Φ D Φ Φ C Φ 17Φ
T
T
T
ch=B
ch=Φ
Λ
T
T= Λ, Creat(T)
ch=A T
A
B creat(T L)
ΛB 返回
creat(T L)
creat(T R)
A
p=p->RChild;
}
2021/2/21
}
top
A
B
C
D
top
B
top
A
A
top
D
A
top
A
top
C
13
top
中序遍历二叉树的非递归算法:
A
void InOrder(BiTree T)
{ InitStack(&S); 相当于top=-1;
p=T;
B
C
while(p!=NULL | | !IsEmpty(S)) 相当于top==-1;
}
后序遍历二叉树的递归算法:
void PostOrder (BiTree T)
{ if(T!=NULL)
{ PostOrder (T->lchild);
PostOrder (T->rchild);
printf(T->data); }
2021/2/21
15
}
先序遍历二叉树的递归算法: void PreOder (BiTree T) { if(T! =NULL){ printf (T->data); PreOrder (T->lchild); PreOrder (T->rchild); } }
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
如何根据前序遍历序列和中序遍历序列确定二叉树
假设某二叉树的先序遍历序列是abdgcefh,中序遍历序列是dgbaechf,画出二叉树,并给出其后序遍历序列。
分析过程:
以下面的例题为例进行讲解:
已知一棵二叉树的先序遍历序列和中序遍历序列分别是abdgcefh、dgbaechf,求二叉树及后序遍历序列。
分析:先序遍历序列的第一个字符为根结点。
对于中序遍历,根结点在中序遍历序列的中间,左边部分是根结点的左子树的中序遍历序列,右边部分是根结点的右子树的中序遍历序列。
先序:abdgcefh --> a bdg cefh
中序:dgbaechf --> dgb a echf
得出结论:a是树根,a有左子树和右子树,左子树有bdg结点,右子树有cefh结点。
先序:bdg --> b dg
中序:dgb --> dg b
得出结论:b是左子树的根结点,b无右子树,有左子树。
先序:dg --> d g
中序:dg --> d g
得出结论:d是b的左子树的根结点,d无左子树,有右子树。
先序:cefh --> c e fh
中序:echf --> e c hf
得出结论:c是右子树的根结点,c有左子树(只有e结点),有右子树(有fh结点)。
先序:fh --> f h
中序:hf --> h f
得出结论:f是c的左子树的根结点,f有左子树(只有h结点),无右子树。
还原二叉树为:
a
b c
d e f
g h
后序遍历序列:gdbehfca。