表达式用二叉树表示(1)
全国计算机等级考试二级公共基础之树与二叉树1

全国计算机等级考试二级公共基础之树与二叉树1.6 树与二叉树1.6.1 树的基本概念树是一种简单的非线性结构。
在树这种结构中,所有元素之间的关系具有明显的层次关系。
用图形表示树这种数据结构时,就象自然界中的倒长的树,这种结构就用“树”来命名。
如图:在树结构中,每个结点只有一个前件,称为父结点,没有前件的结点只有一个,称为树的根结点,简称为树的根(如R)。
在树结构中,每一个结点可以有多个后件,它们都称为该结点的子结点。
没有后件的结点称为叶子结点(如W,Z,A ,L,B,N,O,T,H,X)。
在树结构中,一个结点拥有的后件个数称为结点的度(如R的度为4,KPQDEC 结点度均为2)。
树的结点是层次结构,一般按如下原则分层:根结点在第1层;同一个层所有结点的所有子结点都在下一层。
树的最大层次称为树的深度。
如上图中的树深度为4。
R结点有4棵子树,KPQDEC结占各有两棵子树;叶子没有子树。
在计算机中,可以用树结构表示算术运算。
在算术运算中,一个运算符可以有若干个运算对象。
如取正(+)与取负(-)运算符只有一个运算对象,称为单目运算符;加(+)、减(-)、乘(*)、除(/)、乘幂(**)有两个运算对象,称为双目运算符;三元函数f(x,y,z)为 f函数运算符,有三个运算对象,称为三目运算符。
多元函数有多个运算对象称多目运算符。
用树表示算术表达式原则是:(1)表达式中的每一个运算符在树中对应一个结点,称为运算符结点(2)运算符的每一个运算对象在树中为该运算结点的子树(在树中的顺序从左到右)(3)运算对象中的单变量均为叶子结点根据上面原则,可将表达式:a*(b+c/d)+c*h-g*f表示如下的树。
树在计算机中通常用多重链表表示,多重链表的每个结点描述了树中对应结点的信息,每个结点中的链域(指针域)个数随树中该结点的度而定。
1.6.2 二叉树及其基本性质1. 什么是二叉树二叉树是很有用的非线性结构。
它与树结构很相似,树结构的所有术语都可用到二叉树这种结构上。
实验五 二叉树的应用----表达式求值

浙江大学城市学院实验报告课程名称python高级程序设计实验项目名称实验五二叉树的应用----表达式求值实验成绩指导老师(签名)日期一.实验目的和要求1、掌握二叉树的链式存储结构;2、掌握在二叉链表上的二叉树的基本操作;3、掌握二叉树的简单应用----表达式树的操作。
二.实验内容1、在实验四中,已经实现了对一个中缀表达式可以用栈转换成后缀表达式,并可对后缀表达式进行求值计算的方法。
另一种思路是可以利用二叉树建立表达式树,通过对该表达式树进行求值计算,本实验实现:输入一个中缀表达式,建立该表达式的二叉树,然后对该二叉树进行表达式值的计算。
如一个中缀达式(6+2)*5 的二叉树表示为如下所示时,该二叉树的后序遍历62+5*正好就是后缀表达式。
设一般数学表达式的运算符包括+、-、*、/ 四种,当然允许(),且()优先级高。
为方便实现,设定输入的表达式只允许个位整数。
要求设计一个完整的程序,对输入的一个日常的中缀表达式,实现以下功能:⏹建立对应的二叉树⏹输出该二叉树的前序序列、中序序列、后序序列⏹求该二叉树的高度⏹求该二叉树的结点总数⏹求该二叉树的叶子结点数⏹计算该二叉树的表达式值分析:(1)表达式树的构建方法:●构建表达式树的方法之一:直接根据输入的中缀表达式构建对于任意一个算术中缀表达式,都可用二叉树来表示。
表达式对应的二叉树创建后,利用二叉树的遍历等操作,很容易实现二叉树的求值运算。
因此问题的关键就是如何创建表达式树。
对于一个中缀表达式来说,其表达式对应的表达式树中叶子结点均为操作数,分支结点均为运算符。
由于创建的表达式树需要准确的表达运算次序,因此,在扫描表达式创建表达式树的过程中,当遇到运算符时不能直接创建结点,而应将其与前面的运算符进行优先级比较,根据比较结果进行处理。
这种处理方式在实验四中以采用过,可以借助一个运算符栈,来暂存已经扫描到的还未处理的运算符。
根据表达式树与表达式对应关系的递归定义,每两个操作数和一个运算符就可以建立一棵表达式二叉树,而该二叉树又可以作为另一个运算符结点的一棵子树。
树和二叉树的实验报告

《数据结构》实验报告题目: 树和二叉树一、用二叉树来表示代数表达式(一)需求分析输入一个正确的代数表达式, 包括数字和用字母表示的数, 运算符号+ - * / ^ =及括号。
系统根据输入的表达式建立二叉树, 按照先括号里面的后括号外面的, 先乘后除的原则, 每个节点里放一个数字或一个字母或一个操作符, 括号不放在节点里。
分别先序遍历, 中序遍历, 后序遍历此二叉树, 并输出表达式的前缀式, 中缀式和后缀式。
(二)系统设计1.本程序中用到的所有抽象数据类型的定义;typedef struct BiNode //二叉树的存储类型{char s[20];struct BiNode *lchild,*rchild;}BiTNode,*BiTree;2.主程序的流程以及各程序模块之间的层次调用关系, 函数的调用关系图:3. 列出各个功能模块的主要功能及输入输出参数void push(char cc)初始条件: 输入表达式中的某个符号操作结果: 将输入的字符存入buf数组中去BiTree Create_RTree()初始条件: 给出二叉树的定义表达式操作结果:构造二叉树的右子树, 即存储表达式等号右侧的字符组BiTree Create_RootTree()初始条件: 给出二叉树的定义表达式操作结果:构造存储输入表达式的二叉树, 其中左子树存储‘X’, 根节点存储‘:=’void PreOrderTraverse(BiTree T)初始条件: 二叉树T存在操作结果:先序遍历T, 对每个节点调用函数Visit一次且仅一次void InOrderTraverse(BiTree T)初始条件: 二叉树T存在操作结果:中序遍历T, 对每个节点调用函数Visit一次且仅一次void PostOrderTraverse(BiTree T)初始条件: 二叉树T存在操作结果:后序遍历T, 对每个节点调用函数Visit一次且仅一次int main()主函数, 调用各方法, 操作成功后返回0(三)调试分析调试过程中还是出现了一些拼写错误, 经检查后都能及时修正。
二叉树的广义表表示法__概述及解释说明

二叉树的广义表表示法概述及解释说明1. 引言1.1 概述二叉树是一种常见的数据结构,在计算机科学中广泛应用。
为了有效地表示和操作二叉树,人们提出了各种表示方法。
其中,二叉树的广义表表示法是一种常用且灵活的方式。
1.2 文章结构本文将首先介绍二叉树的广义表表示法的定义和特点。
然后,我们将详细讨论广义表的表示方法,并解释广义表与二叉树之间的关系。
接下来,我们将介绍如何使用广义表表示方法构建二叉树,并讨论相应的转换方法。
最后,我们将探讨在广义表表示法下如何进行遍历和操作二叉树,并提供相应的实现方法和示例场景。
1.3 目的本文的目标是全面而清晰地介绍二叉树的广义表表示法,使读者对该方法有深入理解。
通过学习本文,读者将能够掌握如何使用广义表表示法构建和操作二叉树,并能够在实际问题中应用相关技巧。
同时,本文还旨在帮助读者提高对数据结构和算法相关知识的理解水平,并培养解决实际问题时分析和抽象的能力。
这样,我们完成了“1. 引言”部分的详细撰写。
2. 二叉树的广义表表示法2.1 定义和特点二叉树是一种常用的数据结构,每个节点最多有两个子节点,分别称为左子节点和右子节点。
二叉树的广义表表示法是一种将二叉树以字符串形式进行表示的方法。
在广义表中,以括号形式将二叉树的节点和子树进行包裹,并使用逗号分隔各个元素。
2.2 广义表的表示方法广义表由以下部分组成:- 括号:用来包裹二叉树的节点和子树。
- 节点值:表示该节点存储的数据值。
- 逗号:用于分隔各个元素。
- 空格:可选,用于提高可读性。
例如,假设有一个二叉树如下所示:```A/ \B C/ \D E```它可以表示为广义表形式为:`(A, (B, (), ()), (C, (D, (), ()), (E, (), ())))`解释上述广义表:- `(A`代表当前节点的值为A。
- `(B, (), ())`代表当前节点的左子节点为空并且右子节点为空。
- `(C, (D, (), ()), (E, (), ()))`代表当前节点的左子节点为D、右子节点为E。
算术表达式(例题)-二叉树

最早提出遍历问题的是对存储在计算机中的表达式求值。
例如:(a+b ×(c-d))-e/f 。
表达式用树形来表示,如图8-11-1所示。
运算符在树中放在非终端结点的位置上,操作数放在叶子结点处。
当我们对此二叉树进行先序、中序和后序遍历后,便可得到表达式的前缀、中缀和后缀书写形式:前缀:-+a*b-cd/ef中缀:a+b*c-d-e/f 后缀:abcd-*+ef/-其中,中缀形式是算术表达式的通常形式,只是没有括号。
在计算机内,使用后缀表达式易于求值。
例1 输入一个算术表达式,判断该表达式是否合法,若不合法,给出错误信息;若合法,则输出合法表达式的表达式树。
【算法分析】表达式不合法有三种情况:①左右括号不匹配;②变量名不合法;③运算符两旁无参与运算的变量或数。
分析表达式树可以看到:表达式的根结点及其子树的根结点为运算符,其在树中的顺序是按运算的先后顺序从后到前,表达树的叶子为参与运算的变量或数。
表达式树如图8-11-2处理时,首先找到运算级别最低的运算符“+”作为根结点,继而确定该根结点的左、右子树结点在表达式串中的范围为a 和(b-c)/d ,再在对应的范围内寻找运算级别最低的运算符作为子树的根结点,直到范围内无运算符,则剩余的变量或数为表达式树的叶子。
【算法步骤】① 设数组ex 存放表达式串的各字符,lt 、rt 作为结点的左右指针,变量left 、right 用于存放每次取字符范围的左、右界。
② 设置左界初值为1;右界初值为串长度。
③ 判断左右括号是否匹配,不匹配则认为输入有错误。
④ 在表达式的左右界范围内寻找运算级别最低的运算符,同时判断运算符两旁有否参与运算的变量或数。
若无,则输入表达式不合法;若有,作为当前子树的根结点,设置左子树指针及其左右界值,设置右子树指针及其左右界值。
⑤ 若表达式在左右界范围内无运算符,则为叶子结点,判断变量名或数是否合法。
⑥ 转④,直到表达式字符取完为止。
数据结构实验二叉树

实验六:二叉树及其应用一、实验目的树是数据结构中应用极为广泛的非线性结构,本单元的实验达到熟悉二叉树的存储结构的特性,以及如何应用树结构解决具体问题。
二、问题描述首先,掌握二叉树的各种存储结构和熟悉对二叉树的基本操作。
其次,以二叉树表示算术表达式的基础上,设计一个十进制的四则运算的计算器。
如算术表达式:a+b*(c-d)-e/f三、实验要求如果利用完全二叉树的性质和二叉链表结构建立一棵二叉树,分别计算统计叶子结点的个数。
求二叉树的深度。
十进制的四则运算的计算器可以接收用户来自键盘的输入。
由输入的表达式字符串动态生成算术表达式所对应的二叉树。
自动完成求值运算和输出结果。
四、实验环境PC微机DOS操作系统或Windows 操作系统Turbo C 程序集成环境或Visual C++ 程序集成环境五、实验步骤1、根据二叉树的各种存储结构建立二叉树;2、设计求叶子结点个数算法和树的深度算法;3、根据表达式建立相应的二叉树,生成表达式树的模块;4、根据表达式树,求出表达式值,生成求值模块;5、程序运行效果,测试数据分析算法。
六、测试数据1、输入数据:2.2*(3.1+1.20)-7.5/3正确结果:6.962、输入数据:(1+2)*3+(5+6*7);正确输出:56七、表达式求值由于表达式求值算法较为复杂,所以单独列出来加以分析:1、主要思路:由于操作数是任意的实数,所以必须将原始的中缀表达式中的操作数、操作符以及括号分解出来,并以字符串的形式保存;然后再将其转换为后缀表达式的顺序,后缀表达式可以很容易地利用堆栈计算出表达式的值。
例如有如下的中缀表达式:a+b-c转换成后缀表达式为:ab+c-然后分别按从左到右放入栈中,如果碰到操作符就从栈中弹出两个操作数进行运算,最后再将运算结果放入栈中,依次进行直到表达式结束。
如上述的后缀表达式先将a 和b 放入栈中,然后碰到操作符“+”,则从栈中弹出a 和b 进行a+b 的运算,并将其结果d(假设为d)放入栈中,然后再将c 放入栈中,最后是操作符“-”,所以再弹出d和c 进行d-c 运算,并将其结果再次放入栈中,此时表达式结束,则栈中的元素值就是该表达式最后的运算结果。
二叉树 c语言

二叉树 c语言在计算机科学领域中,树型数据结构是一种非常重要的数据结构,在实际开发中也得到了广泛的应用。
其中,二叉树又是一种非常常见的树型结构。
二叉树在很多情况下都能够提供更好的算法效率,同时也易于理解和实现,因此我们可以通过通过学习和掌握二叉树的特点以及优点,来更好的应用到实际开发中。
一、二叉树的定义二叉树是一种树型结构,树型结构是由节点构成的。
二叉树与一般的树型结构不同,它的每个节点最多只有两个子节点,分别称为左子树和右子树。
它们可以为空或者不为空,其子节点的数量时不固定且没有任何限制的。
二叉树的定义如下:(1)空树是树的一种特殊的状态。
我们可以把它称为二叉树;(2)若不是空树,那么它就是由一个称为根节点(root)的元素和左右两棵分别称为左子树(left subtree)和右子树(right subtree)的二叉树组成。
二、二叉树的特性(1)每个节点最多只有两个子节点,分别称为左子节点和右子节点;(2)左子树和右子树是二叉树;(3)二叉树没有重复的节点。
三、二叉树的应用二叉树是一种非常实用的数据结构,因为它可以模拟很多实际生活中的情况。
例如,我们可以利用二叉树来对某些数据进行分类和排序。
在二叉树的基础上,我们还可以构造二叉堆、哈夫曼树等更高级的数据结构。
除此之外,二叉树还可以应用到程序设计中。
例如,我们可以构造一个二叉树来表示某个程序的控制流,这个程序在执行时可以沿着二叉树的各个节点进行分支和选择,实现不同的功能。
此外,我们还可以利用二叉树来加快某些算法的执行效率,比如二分查找算法等。
四、二叉树的遍历方式对于二叉树的遍历,有三种基本方式,即前序遍历、中序遍历、后序遍历。
它们的遍历顺序不同,因此也得到了不同的称呼。
下面我们来简要介绍一下这三种遍历方式的特点和应用。
(1)前序遍历前序遍历是指首先访问树的根节点,然后按照从左到右的顺序依次遍历左子树和右子树。
前序遍历的应用非常广泛,可以用于生成表达式树、构造二叉树等等。
c语言基于二叉树的表达式求值算法

c语言基于二叉树的表达式求值算法C语言中,基于二叉树的表达式求值算法主要包括两部分:中缀表达式转换为后缀表达式和后缀表达式求值。
1.中缀表达式转换为后缀表达式中缀表达式是我们常见的数学表达方式,例如3 + 4 * 2 - 5。
为了方便计算机求值,我们需要将中缀表达式转换为后缀表达式,也叫做逆波兰表达式。
转换的过程使用栈数据结构来实现。
具体算法如下:1.定义一个栈和一个结果字符串,栈用于存储操作符,结果字符串用于保存后缀表达式。
2.从左到右遍历中缀表达式的每一个字符。
3.如果当前字符是数字,直接将其加入结果字符串。
4.如果当前字符是左括号"(",将其入栈。
5.如果当前字符是右括号")",则依次将栈顶的操作符弹出并加入结果字符串,直到遇到左括号为止,同时将左括号从栈中弹出。
6.如果当前字符是操作符,需要将栈中优先级比当前操作符高或者相等的操作符弹出并加入结果字符串,然后将当前操作符入栈。
7.遍历完所有字符后,将栈中剩余的操作符依次弹出并加入结果字符串。
8.最终结果字符串就是后缀表达式。
例如,对于中缀表达式3 + 4 * 2 - 5,转换为后缀表达式为3 4 2 * + 5 -2.后缀表达式求值后缀表达式求值算法使用栈数据结构来实现。
具体算法如下:1.定义一个栈,用于存储操作数。
2.从左到右遍历后缀表达式的每一个字符。
3.如果当前字符是数字,则将其转换为对应的整数并入栈。
4.如果当前字符是操作符,则从栈中弹出两个操作数,先弹出的作为右操作数,后弹出的作为左操作数,根据操作符进行运算,得到结果后入栈。
5.遍历完所有字符后,栈顶的数字即为最终的结果。
例如,对于后缀表达式3 4 2 * + 5 -,求值的过程如下:1.入栈3。
2.入栈4。
3.入栈2。
4.弹出2和4,计算4 * 2 = 8,将8入栈。
5.弹出8和3,计算3 + 8 = 11,将11入栈。
6.入栈5。
7.弹出5和11,计算11 - 5 = 6,得到最终结果。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构程序报告(3)2011.3.292. 需求分析:(1)功能:表达式可以用二叉树表示,对于简单的四则运算,请实现以下功能【1】对于任意给出的前缀表达式(不带括号)、中缀表达式(可以带括号)或后缀表达式(不带括号),能够在计算机内部构造出一棵表达式二叉树,并且图示出来(图形的形式)。
【2】对于构造好的内部表达式二叉树,按照用户的要求输出相应的前缀表达式(不带括号)、中缀表达式(可以带括号,但不允许冗余括)或后缀表达式(不带括号)。
提示:所谓中缀表达式中的冗余括号,就是去掉括号后不影响表达式的计算顺序。
例如:“(c+b)+a”中的括号是冗余的,可以表示成不冗余的“c+b+a”。
(2)输入输出要求:请输入字符串表达式:树形二叉树(图形显示)中缀表达式为:前缀表达式为:后缀表达式为:3.概要设计:(算法)分成两部分完成:【1】前缀、中缀、后缀表达式->二叉树表达式前缀表达式->二叉树表达式:(a)碰到操作数则把其值赋给相应的新申请的二叉树结点,地址压栈;(b)碰到操作符则把其值赋给相应的新申请的二叉树,并从栈中弹出两个地址,分别作为其右指针和左指针,然后再把其地址压栈,最后一个地址即为二叉树的根结点地址。
中缀表达式->二叉树表达式:把中缀表达式转换成后缀表达式,然后再建立二叉树。
后缀表达式->二叉树表达式:(a)碰到操作数则把其值赋给相应的新申请的二叉树结点,若栈为空则地址压栈,若非空则取栈顶元素,若栈顶元素的左孩子为空则当前结点设为其左孩子,左孩子为满则设为其右孩子再压栈;(b)碰到操作数则把其值赋给相应的新申请的二叉树结点,取栈顶元素,若栈顶元素的左孩子为空则设为其左孩子,左孩子为满则设为其右孩子开始那个元素地址为根结点地址,开始时用变量root保存。
【1】二叉树表达式->前缀、中缀、后缀表达式二叉树表达式->前缀表达式:对二叉树表达式进行前序遍历。
二叉树表达式->中缀表达式:对二叉树表达式进行中序遍历,若结点操作符的优先级高于其左或右子树,在打印相应的子树之前先打印开括号,在打印相应的子树最后在打印一个闭括号。
二叉树表达式->后缀表达式:对二叉树表达式进行后序遍历。
建立表达式树就是建立树中的每一个结点,将每一个结点链接起来就是整棵树。
而在建立深度低的结点时要将其左右指针指向之前建立的深度比它高一级的结点(如’*’要指向’2’和’3’,而’+’又要指向’*’)。
这样我们可以用栈来存放每次建立的结点,按照优先级(表达式为中缀型)或顺序扫描表达式(表达式为波兰式与逆波兰式)建立每一个结点。
建立结点的顺序即为表达式求值的顺序。
如果扫描到操作数则直接新建一个左右指针为空的结点,并压入结点栈中(存放结点指针)。
遇到运算符时首先新建一个结点,然后从栈中依次弹出两个结点,并让新建立的结点的左右指针域指向它们。
当所有结点建立完毕时,如果表达式没有错误(这里假设输入表达式正确),这时栈中应该只剩下一个结点,它就是所建立的表达式的根结点。
4. 详细设计:(具体方法)首先创建一个节点类TNode:包含操作符oper、左孩子left、右孩子right,isOper ()判断是否为操作符,getOperOrder()返回运算符op所对应的优先级,freeTree()程序结束销毁二叉树,postOrder()先序遍历,preOrder()后序遍历,inOrder()中序遍历,ExpTree1()后缀表达式生成二叉树,ExpTree3()前缀表达式生成二叉树,ExpTree2()中后缀表达式生成二叉树,count()求值函数,paint()输出函数附程序:#include <iostream>#include <stack>#include <queue>#include <string>#include<math.h>using namespace std;class TNode//节点类{ public:char oper;TNode *left;TNode *right;int s;int t;TNode(){ left=right=NULL;oper=0;}TNode(char op){ left=right=NULL;oper=op;}};bool isOper(char op)//判断是否为运算符{char oper[]={'(',')','+','-','*','/','^'};for(int i=0;i<sizeof(oper);i++){ if(op==oper[i]){return true;} }return false;}int getOperOrder(char op)//返回运算符op所对应的优先级{ switch(op){ case '(':return 1;case '+':case '-':return 2;case '*':case '/':return 3;case '^':return 4;default://定义在栈中的右括号和栈底字符的优先级最低return 0;} }void freeTree(TNode *&p)//释放树{ if(p->left!=NULL)freeTree(p->left);if(p->right!=NULL)freeTree(p->right);delete(p);cout<<"Memory free "; }void postOrder(TNode *p) //先序遍历{ if(p){ postOrder(p->left);postOrder(p->right);cout<<p->oper;} }void preOrder(TNode *p) //后序遍历{ if(p){ cout<<p->oper;preOrder(p->right);} }void inOrder(TNode *p)//中序遍历{ if(p){ if(p->left){ if(isOper(p->left->oper)&& getOperOrder(p->left->oper)<getOperOrder(p->oper)){ cout<<"(";inOrder(p->left);cout<<")";}else{inOrder(p->left);} }cout<<p->oper;if(p->right){ if(isOper(p->right->oper)&& getOperOrder(p->right->oper)<=getOperOrder(p->oper)){ cout<<"(";cout<<")";}else{inOrder(p->right);} } } }void ExpTree1(TNode *&p,string str)//后缀表达式生成二叉树{stack <TNode*> nodeStack;char temp;int i=0;temp=str[i++];while(temp!='\0'){ if(temp!='\0'&&!isOper(temp))//不是运算符,则进栈{ p=new TNode(temp);//以temp为结点值构造二叉树结点nodeStack.push(p);temp=str[i++];}else{ p=new TNode(temp);if(nodeStack.size()){ p->right=nodeStack.top();//若非空则弹栈并设为结点的右孩子nodeStack.pop(); }if(nodeStack.size()){ p->left=nodeStack.top();//若非空则弹栈并设为结点的左孩子nodeStack.pop(); }nodeStack.push(p);temp=str[i++];} } }void ExpTree3(TNode *&p, string str)//前缀表达式生成二叉树{ stack <TNode*> nodeStack;char temp;int i=str.size()-1;temp=str[i--];while(temp!='\0'){ if(temp!='\0'&&!isOper(temp)){ p=new TNode(temp);//以temp为内容来建立新的结点nodeStack.push(p);temp=str[i--];}else{ p=new TNode(temp);if(nodeStack.size())//若栈顶指针所指结点左孩子为空{ p->left=nodeStack.top(); //则当前结点设置成其左孩子nodeStack.pop();} if(nodeStack.size())//若栈顶指针所指结点右孩子为空{ p->right=nodeStack.top();//则当前结点设置成其右孩子nodeStack.pop();//栈顶元素左右孩子指针设置完毕弹出}nodeStack.push(p);temp=str[i--];} } }void ExpTree2(TNode *&p, string str)//中缀表达式转换成后缀表达式生成二叉树{ stack<char> a;char temp;string Postfixexp="";int i=0;temp=str[i++];while(temp!='\0'){ if(!isOper(temp)){ Postfixexp+=temp;temp=str[i++];}else if(temp=='(')//进栈{ a.push(temp);temp=str[i++];}else if(temp==')'){while(a.top()!='(')//脱括号{ Postfixexp+=a.top();a.pop();//在碰到开括号和栈为空前反复弹出栈中元素}a.pop();temp=str[i++];}else if(temp=='+'||temp=='-'||temp=='*'||temp=='/')//出栈{ while(!a.empty()&&a.top()!='('&&getOperOrder(a.top())>=getOperOrder(tem p))//若栈非空栈顶不是左括号且栈顶元素优先级不低于输入运算符时,//将栈顶元素弹出到后缀表达式中,并且str下标加1{ Postfixexp+=a.top();a.pop(); }a.push(temp);temp=str[i++];} }while(!a.empty()){ Postfixexp+=a.top();a.pop();}ExpTree1(p,Postfixexp); }void count(TNode *p,int &height,int n)//求值函数{ if(p->left==NULL&&p->right==NULL){ if(n>height)height=n;}if(p->left!=NULL)count(p->left,height,n+1);if(p->right!=NULL)count(p->right,height,n+1); } void paint(TNode *p)//输出函数{ int height=0;int h=0;int i;using std::queue;queue<TNode*> aQueue;count(p,height,1);TNode *pointer=p;TNode *lastpointer;if(pointer){ pointer->s=1;pointer->t=1;aQueue.push(pointer); }while(!aQueue.empty()){ lastpointer=pointer;pointer=aQueue.front(); aQueue.pop();if(pointer->s>h){cout<<endl;h=pointer->s;}if(pointer->t==1){for(i=0;i<pow(2,height-pointer->s)-1;i++)cout<<" ";}else if(lastpointer->s!=pointer->s){for(i=0;i<(pointer->t-1)*(pow(2,height-pointer->s+1)-1)+(pointer->t-1)-1+pow(2, height-pointer->s);i++)cout<<" "; }else{ for(i=0;i<(pointer->t-lastpointer->t)*(pow(2,height-pointer->s+1)-1)+(pointer->t -lastpointer->t)-1;i++)cout<<" "; }cout<<pointer->oper;if(pointer->left!=NULL){pointer->left->s=pointer->s+1;pointer->left->t=pointer->t*2-1;aQueue.push(pointer->left);}if(pointer->right!=NULL){pointer->right->s=pointer->s+1;pointer->right->t=pointer->t*2;aQueue.push(pointer->right);} } }int main(){ string expression;TNode *tree;cout<<endl<<"请输入字符串表达式:";cin>>expression;if(isOper(expression[0]))ExpTree3(tree,expression);else if(isOper(expression[1]))ExpTree2(tree,expression);elseExpTree1(tree,expression);paint(tree);cout<<endl;cout<<"中缀表达式为:";inOrder(tree);cout<<endl;cout<<"前缀表达式为:";preOrder(tree);cout<<endl;cout<<"后缀表达式为:";postOrder(tree);cout<<endl;freeTree(tree);cout<<endl;system("pause");return 0; }5.测试数据:(1)请输入字符串表达式:-+1*234-+ 41*2 3中缀表达式为:1+2*3-4前缀表达式为:-+1*234后缀表达式为:123*+4-memory free memory free memory free memory free memory free 请按任意键继续………………………..(2)请输入字符串表达式:1+2*3-4-+ 41*2 3中缀表达式为:1+2*3-4前缀表达式为:-+1*234后缀表达式为:123*+4-memory free memory free memory free memory free memory free请按任意键继续………………………..(3)请输入字符串表达式:123*+4--+ 41*2 3中缀表达式为:1+2*3-4前缀表达式为:-+1*234后缀表达式为:123*+4-memory free memory free memory free memory free memory free请按任意键继续………………………..测试截图:6.总结:程序调试中的问题及解决方法:前缀表达式建树,通过入栈出栈操作求出前缀表达式的逆序,针对得到的逆序表达式通过后缀表达式建立二叉树的方法,遇到操作数则入栈,遇到操作符则从栈中弹出两个操作数构建一棵小的二叉树,然后将小树的根节点入栈以便于下次操作。