二叉树表达式求值

合集下载

实验五 二叉树的应用----表达式求值

实验五  二叉树的应用----表达式求值

浙江大学城市学院实验报告课程名称python高级程序设计实验项目名称实验五二叉树的应用----表达式求值实验成绩指导老师(签名)日期一.实验目的和要求1、掌握二叉树的链式存储结构;2、掌握在二叉链表上的二叉树的基本操作;3、掌握二叉树的简单应用----表达式树的操作。

二.实验内容1、在实验四中,已经实现了对一个中缀表达式可以用栈转换成后缀表达式,并可对后缀表达式进行求值计算的方法。

另一种思路是可以利用二叉树建立表达式树,通过对该表达式树进行求值计算,本实验实现:输入一个中缀表达式,建立该表达式的二叉树,然后对该二叉树进行表达式值的计算。

如一个中缀达式(6+2)*5 的二叉树表示为如下所示时,该二叉树的后序遍历62+5*正好就是后缀表达式。

设一般数学表达式的运算符包括+、-、*、/ 四种,当然允许(),且()优先级高。

为方便实现,设定输入的表达式只允许个位整数。

要求设计一个完整的程序,对输入的一个日常的中缀表达式,实现以下功能:⏹建立对应的二叉树⏹输出该二叉树的前序序列、中序序列、后序序列⏹求该二叉树的高度⏹求该二叉树的结点总数⏹求该二叉树的叶子结点数⏹计算该二叉树的表达式值分析:(1)表达式树的构建方法:●构建表达式树的方法之一:直接根据输入的中缀表达式构建对于任意一个算术中缀表达式,都可用二叉树来表示。

表达式对应的二叉树创建后,利用二叉树的遍历等操作,很容易实现二叉树的求值运算。

因此问题的关键就是如何创建表达式树。

对于一个中缀表达式来说,其表达式对应的表达式树中叶子结点均为操作数,分支结点均为运算符。

由于创建的表达式树需要准确的表达运算次序,因此,在扫描表达式创建表达式树的过程中,当遇到运算符时不能直接创建结点,而应将其与前面的运算符进行优先级比较,根据比较结果进行处理。

这种处理方式在实验四中以采用过,可以借助一个运算符栈,来暂存已经扫描到的还未处理的运算符。

根据表达式树与表达式对应关系的递归定义,每两个操作数和一个运算符就可以建立一棵表达式二叉树,而该二叉树又可以作为另一个运算符结点的一棵子树。

基于二叉树结构的表达式求值算法

基于二叉树结构的表达式求值算法

实验报告课程名称: 程序设计与数据结构 指导老师: ljq 成绩: 实验名称:基于二叉树结构的表达式求值算法 实验类型: 上机 同组学生姓名:一、实验目的和要求(必填)三、代码缺陷及修正记录五、讨论、心得二、实验内容和代码(必填) 四、实验结果与分析(必填)一、实验目的和要求1. 掌握编程工具的使用2. 掌握二叉树数据结构在计算机上的实现3. 掌握通过计算机编程解决问题的基本方法二、实验内容和代码1.实验内容:● 编程实现基于二叉树结构的表达式求值算法● 表达式包含加减乘除四则运算以及至少一层括弧运算● 首先将输入的原表达式转换成二叉树结构,然后采用二叉树的后序递归遍历方法求得表达式的值● 将所有实验内容合并到一个工程,增加交互操作和循环处理(持续)2.代码1.头文件expnbitree .h装订 线1 2 3 4 5 6 7 8 91011121314151617181920212223 #include<stdio.h>#include<string.h>#include<stdlib.h>#define EXP_LEN 100 //定义表达式的最大长度#define DATA_LEN 20 //定义每个操作数的最大长度typedef struct BiTNode{int dflag; //标志域,值为1,data[]存放操作运算符;值为0,data[]存放操作数char data[DATA_LEN + 1]; //数据域,存放:操作运算符或操作数struct BiTNode *lchild, *rchild; //分别指向结点的左、右子树}BiTNode, *BiTree; //定义二叉树结点及二叉树类型指针int CreateBiTree(BiTree &bt, char *p, int len);//创建二叉树,并用bt返回树的根地址,p为表达式的首地址,l为表达式的长度int Calculate(BiTree bt, double &rst);//计算表达式的值,bt为据表达式创建的二叉树,用rst返回表达式的值int PreOrderTraverse(BiTree bt);//先序遍历二叉树bt,输出先序遍历序列int InOrderTraverse(BiTree bt); //中序遍历二叉树bt,输出中序遍历序列int PostOrderTraverse(BiTree bt); //后序遍历二叉树bt,输出后序遍历序列int DestroyBiTree(BiTree &bt); //销毁二叉树//二叉树结构的表达式求解算法入口void expnbitree();2.源文件expntree.c1 2 3 4 5 6 7 8 910111213141516 #include<stdio.h>#include<string.h>#include<stdlib.h>#include"expnbitree.h"//ExpnBiTree实现子程序入口void expnbitree(){int n, len, i; //n标志量,值为0,退出程序;len存储表达式的长度;i一般变量char expn[EXP_LEN + 1]; //存放表达式double rst; //存放表达式计算结果BiTree bt = NULL; //声明一个二叉树gets_s(expn);do{1718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 i = 0;printf("请输入合法的表达式:\n");gets_s(expn);for (i = 0, len = 0; expn[i] != '\0'; i++) //去掉表达式中的空格,并计算表达式的长度if (expn[i] != ' ')expn[len++] = expn[i];expn[len] = '\0';printf("正在构建二叉树……\n");if (CreateBiTree(bt, expn, len))printf("二叉树构建成功!\n");else{ //销毁未成功建立的二叉树,释放动态申请的内存printf("二叉树构建失败!\n");printf("将销毁二叉树…………");if (DestroyBiTree(bt))printf("二叉树销毁成功!\n");else {printf("二叉树销毁失败!\n");exit(0);}continue;}printf("输出表达式的先序遍历序列……:\n");PreOrderTraverse(bt);printf("\n");printf("输出表达式的中序遍历序列……:\n");InOrderTraverse(bt);printf("\n");printf("输出表达式的后序遍历序列……:\n");PostOrderTraverse(bt);printf("\n");printf("计算表达式的值……:\n");if (Calculate(bt, rst))printf("%g\n", rst);elseprintf("计算表达式的值失败!\n");printf("即将销毁二叉树…………");if (DestroyBiTree(bt))printf("二叉树销毁成功!\n");else {printf("二叉树销毁失败!\n");exit(0);}printf("如果要继续计算下一个表达式,请输入1,否则,返回上一级:\n ");616263646566676869707172737475767778798081828384858687888990919293949596979899 100 101 102 103 104scanf_s("%d", &n);getchar();} while (n==1);}//创建二叉树int CreateBiTree(BiTree &bt, char *p, int len){int i = 0, lnum = 0, rpst1 = -1, rpst2 = -1, pn = 0;//lnum记录"("的未成对个数;//rpst1/rpst2记录表达式中优先级最低的("*"、"/")/("+"、"-")的位置;//pn记录操作数中"."的个数,以判断输入操作数是否合法if (len == 0)return 1;if (!(bt = (BiTree)malloc(sizeof(BiTNode)))) {printf("内存申请失败\n");return 0;}else{//初始化bt->lchild = bt->rchild = NULL;memset(bt->data, '\0', sizeof(bt->data));//memset是计算机中C/C++语言函数——memset(void*s,int ch,size_t n);//将s所指向的某一块内存中的后n个字节的内容全部设置为ch指定的ASCII值,//第一个值为指定的内存地址,块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作,其返回值为s。

基于二叉树的表达式求值算法实验报告

基于二叉树的表达式求值算法实验报告

基于二叉树的表达式求值算法实验报告一、实验目的1. 学习基于二叉树的表达式求值算法。

2. 掌握二叉树的遍历方法和递归算法。

3. 设计并实现基于二叉树的表达式求值程序。

二、实验环境操作系统:Windows 10开发环境:Visual Studio Code 1.57.1编程语言:C++三、算法描述1. 表达式转二叉树将中缀表达式转换为二叉树的过程可以通过递归算法实现。

具体步骤如下:(1)如果表达式只有一个数字,那么将其作为叶子节点返回。

(2)如果表达式包含多个操作符,则以操作符优先级最低的操作符为根节点,将表达式分成两部分,分别递归处理左子树和右子树。

(3)如果表达式中有括号,则将括号中的表达式作为一棵子树递归处理。

2. 表达式求值二叉树求值的过程可以通过递归算法实现。

对于一个二叉树节点,分别计算其左子树和右子树的值,并根据节点的操作符计算节点的值。

具体步骤如下:(1)如果节点是叶子节点,则其值为对应数字。

(2)如果节点是加法节点,则将左右子树的值相加。

(3)如果节点是减法节点,则将左子树的值减去右子树的值。

(4)如果节点是乘法节点,则将左右子树的值相乘。

(5)如果节点是除法节点,则将左子树的值除以右子树的值。

四、实验步骤1. 定义二叉树节点结构体c++struct node {char oper; 节点的操作符double val; 节点的值node* left; 左子树节点node* right; 右子树节点};2. 实现表达式转二叉树函数c++node* expressionToTree(string exp) { int len = exp.length();node* root = NULL;如果表达式是一个数字if (len == 1) {root = new node;root->oper = '#';root->val = exp[0] - '0';root->left = NULL;root->right = NULL;return root;}如果表达式包含多个操作符int pos = 0, priority = 0;for (int i = 0; i < len; i++) {if (exp[i] == '(') {priority += 10;continue;}if (exp[i] == ')') {priority -= 10;continue;}if (exp[i] == '+' exp[i] == '-') {if (priority <= 1) {root = new node;root->oper = exp[i];root->left = expressionT oTree(exp.substr(pos, i - pos));root->right = expressionToTree(exp.substr(i + 1));return root;}}if (exp[i] == '*' exp[i] == '/') {if (priority <= 2) {root = new node;root->oper = exp[i];root->left = expressionT oTree(exp.substr(pos, i - pos));root->right = expressionToTree(exp.substr(i + 1));return root;}}}return root;}3. 实现表达式求值函数c++double evaluate(node* root) {if (root == NULL) return 0.0;if (root->left == NULL && root->right == NULL) return root->val;double left_val = evaluate(root->left), right_val =evaluate(root->right);switch (root->oper) {case '+': return left_val + right_val;case '-': return left_val - right_val;case '*': return left_val * right_val;case '/': return left_val / right_val;default: return 0.0;}}4. 测试程序c++int main() {string exp = "((5-2)*(3+4))/7";node* root = expressionToTree(exp);cout << exp << " = " << evaluate(root) << endl; 输出结果为3 return 0;}五、实验结果分析本实验设计并实现了基于二叉树的表达式求值程序。

二叉树计算表达式

二叉树计算表达式

二叉树计算表达式计算表达式是计算机科学中常见的任务,而二叉树是一种常用的数据结构,用于表示表达式。

本文将介绍二叉树如何表示和计算表达式。

一、二叉树表示表达式二叉树是由节点和边组成的树状结构。

每个节点都包含一个值和两个指向左右子节点的指针。

二叉树可以用来表示数学表达式。

例如,下面是一个包含加、减、乘、除的表达式:```5 + 3 *6 / 2 - 4```将表达式转化为二叉树表示,根节点为`-`,其左子树是`+`,右子树是`4`。

`+`节点的左子树为`5`,右子树为`/`。

`/`节点的左子树为`*`,右子树为`2`。

`*`节点的左子树为`3`,右子树为`6`。

```-/ \+ 4/ \5 // \* 2/ \3 6```每个节点的值表示该节点的操作符或操作数。

叶子节点是操作数,内部节点是操作符。

二、计算二叉树表达式计算表达式需要递归地对二叉树进行遍历。

从根节点开始,如果是操作符节点,就对其左右子节点进行递归。

如果是操作数节点,就返回该节点的值。

等到递归完成后,就可以根据操作符节点的值和左右子节点的值对表达式进行计算了。

对于上面的表达式二叉树,计算的过程如下。

首先计算根节点的左右子节点,即`+`节点和`4`节点的值。

`+`节点还需要计算其左右子节点`5`和`/`节点的值。

`/`节点又需要计算其左右子节点`*`和`2`的值。

`*`节点需要计算其左右子节点`3`和`6`的值。

归纳起来,计算的顺序是从下到上,从左到右。

```-/ \+ 4/ \5 // \* 2/ \3 6```按照计算顺序求值:1. 计算`3 * 6`,得到18。

2. 计算`6 / 2`,得到3。

3. 计算`3 / 3`,得到1。

4. 计算`5 + 1`,得到6。

5. 计算`6 - 4`,得到2。

因此,表达式`5 + 3 * 6 / 2 - 4`的值是2。

三、扩展上面的例子说明了如何将表达式转为二叉树,并计算表达式的值。

但实际中会有更复杂的表达式,如函数调用、变量引用等。

完全二叉树的总结点数公式

完全二叉树的总结点数公式

完全二叉树的总结点数公式完全二叉树是一种特殊的二叉树结构,它的每个节点都有两个子节点,除了最后一层的叶子节点外,其他层的节点都是满的。

在完全二叉树中,叶子节点只会出现在最后一层或者倒数第二层,并且最后一层的叶子节点都靠左排列。

在这篇文章中,我们将探讨完全二叉树的总结点数公式以及相关的性质。

完全二叉树的总结点数公式是一个重要的数学公式,它可以帮助我们计算完全二叉树中节点的数量。

这个公式的表达式如下:总结点数 = 2的h次方 - 1其中,h代表完全二叉树的高度。

这个公式的推导过程是基于完全二叉树的性质而得出的。

在完全二叉树中,每一层的节点数都是满的,除了最后一层。

因此,在计算总结点数时,我们只需要计算除了最后一层外的节点数量,然后再加上最后一层的节点数即可。

我们来看完全二叉树的第一层。

由于完全二叉树的定义,第一层只有一个节点,即根节点。

因此,第一层的节点数为1。

接下来,我们来看完全二叉树的第二层。

根据完全二叉树的定义,第二层的节点数等于第一层节点数的两倍,即2。

继续往下,我们可以得到第三层的节点数为4,第四层的节点数为8,以此类推。

可以观察到,每一层的节点数都是2的次方。

因此,我们可以用2的h次方来表示每一层的节点数。

接下来,我们需要计算除了最后一层之外的节点数。

在完全二叉树中,除了最后一层的节点数是满的,其他层的节点数都是满的。

如果完全二叉树的高度为h,那么除了最后一层之外的节点数可以用以下公式表示:除最后一层之外的节点数 = 2的(h-1)次方 - 1接下来,我们需要计算最后一层的节点数。

根据完全二叉树的定义,最后一层的节点数是小于或等于前面各层节点数的两倍。

因此,最后一层的节点数可以用以下公式表示:最后一层的节点数 = 2的(h-1)次方或者 2的h次方 - 2的(h-1)次方我们将除了最后一层之外的节点数和最后一层的节点数相加,即可得到完全二叉树的总结点数。

将上述公式代入,我们可以得到完全二叉树的总结点数公式:总结点数 = 2的(h-1)次方 - 1 + 2的h次方 - 2的(h-1)次方简化上述公式,我们可以得到:总结点数 = 2的h次方 - 1这就是完全二叉树的总结点数公式。

算术表达式(例题)-二叉树

算术表达式(例题)-二叉树

最早提出遍历问题的是对存储在计算机中的表达式求值。

例如:(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 运算,并将其结果再次放入栈中,此时表达式结束,则栈中的元素值就是该表达式最后的运算结果。

后序遍历二叉树实现表达式求值

后序遍历二叉树实现表达式求值
关键词 :中缀表达式 ; 后序遍历 ;表达式求值 中 图分类号 :T P 3 1 文献标识 码 : A
表达式求值是数据结构 中常见的问题 , 传统的求值方法效率较低. 本文 以逻辑运算为例 , 采用 二叉树 作为表达式的存储结构… , 对二叉树进行后序遍历来实现表达式求值 , 提高了运算效率. 尤其适用于对 同

表 达式 中的变 量赋 予 多组 不 同初值 的情 况 , 比如判 断 表达 式 的 类 型 、 求 解 表 达 式 的成 真 赋值 等 , 从 而 可
扩展 应用 到 逻辑 问题 解决 方 案 的求解 等 领域 中.
1 算法设计
运用 二叉 树 实现 表达 式求 值 需解 决 两 个 大 问题 : 表 达 式 的存 储 与 表 达式 求 值 . 本 文 约定 以逻 辑 运 算 为例 , 分别 用 “ &” 、 “ I ” 、 “一” 表示与、 或、 非 三种 逻辑 运算 . 第一 , 表 达式 存储 算 法设计 . 表 1 算符优先关系表
0 1
0 0
O 1
Байду номын сангаас
为“ 与” 运算的运算规则 , 其他运算类似. ( 2 ) 表达式求值.
求值 过程 中只需建 立一个 存放 操作 数 的栈 即可 . 首先 应 该 明确 一 点 : 在存 储 了表 达式 的二叉 树 中 , 操 作 数都 是 叶子结点 , 运算 符都 是分 支结 点. 后 序遍 历该 二叉 树 , 遵循“ 左~ 右一 中” 的顺 序访 问二叉 树 的各
收 稿 日期 : 2 0 1 4 . 1 1 — 1 3
作 者简介 : 潘风 ( 1 9 8 l 一) , 女, 黑龙 江黑 河人 , 运城学 院计 算机科 学与 技术 系讲师 , 工学 硕士 , 主要 从事 网络技术 及应用 方

c语言基于二叉树的表达式求值算法

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,得到最终结果。

利用二叉树求表达式的值

利用二叉树求表达式的值

利⽤⼆叉树求表达式的值利⽤⼆叉树求表达式的值,⾸先要注意表达式中先乘除后加减的运算顺序,所以在建⽴树的过程中,就要将加减尽量作为根节点,最后⼀个加减号作为根节点。

建完树之后是运算过程,采⽤树的后序遍历来运算。

⼆叉树的节点结构,其中值的类型⽤char型struct node{char data;node* left;node* right;};node *CRTree(char s[],int begin,int end){node *p;int k,plus=0,posi;if (begin==end) //只有⼀个字符,构造的是⼀个叶⼦节点{p=(node *)malloc(sizeof(node)); //分配存储空间p->data=s[begin]; //值为s[begin]p->left=NULL;p->right=NULL;return p;}//以下为begin!=end的情况for (k=begin; k<=end; k++)if (s[k]=='+' || s[k]=='-'){plus++;posi=k; //最后⼀个+或-的位置}if (plus==0) //没有+或-的情况(因为若有+、-,前⾯必会执⾏plus++)for (k=begin; k<=end; k++)if (s[k]=='*' || s[k]=='/'){plus++;posi=k;}//以上的处理考虑了优先将+、-放到⼆叉树较⾼的层次上//由于将来计算时,运⽤的是后序遍历的思路//处于较低层的乘除会优先运算//从⽽体现了“先乘除后加减”的运算法则//创建⼀个分⽀节点,⽤检测到的运算符作为节点值if (plus!=0){p=(node *)malloc(sizeof(node));p->data=s[posi]; //节点值是s[posi]p->left=CRTree(s,begin,posi-1); //左⼦树由s[begin]⾄s[posi-1]构成p->right=CRTree(s,posi+1,end); //右⼦树由s[posi+1]到s[end]构成return p;}else//若没有任何运算符,返回NULLreturn NULL;}下⾯是运算过程double Comp(node *b){double v1,v2;if (b==NULL)return0;if (b->left==NULL && b->right==NULL) //叶⼦节点,应该是⼀个数字字符(本项⽬未考虑⾮法表达式)return b->data-'0'; //叶⼦节点直接返回节点值,结点中保存的数字⽤的是字符形式,所以要-'0'v1=Comp(b->left); //先计算左⼦树v2=Comp(b->right); //再计算右⼦树switch(b->data) //将左、右⼦树运算的结果再进⾏运算,运⽤的是后序遍历的思路{case'+':return v1+v2;case'-':return v1-v2;case'*':return v1*v2;case'/':if (v2!=0)return v1/v2;elseabort();}}最后要记得将新建的⼆叉树销毁void DestroyBTNode(node *&b) //销毁⼆叉树{if (b!=NULL){DestroyBTNode(b->left);DestroyBTNode(b->right);free(b);}}。

简单算术表达式的二叉树的构建和求值

简单算术表达式的二叉树的构建和求值

一、概述二、算术表达式的二叉树表示1. 什么是二叉树2. 算术表达式的二叉树表示方法三、算术表达式二叉树的构建1. 中缀表达式转换为后缀表达式2. 后缀表达式构建二叉树四、算术表达式二叉树的求值五、应用举例六、总结一、概述在数学和计算机科学中,处理算术表达式是一个常见的问题。

在计算机中,算术表达式通常以中缀、前缀或后缀的形式出现,其中中缀表达式最为常见。

而采用二叉树来表示和求解算术表达式,是一种常见且高效的方法。

二、算术表达式的二叉树表示1. 什么是二叉树二叉树是一种树形数据结构,它的每个节点最多只能有两个子节点,分别是左子节点和右子节点。

二叉树可以为空,也可以是非空的。

2. 算术表达式的二叉树表示方法在二叉树中,每个节点要么是操作符,要么是操作数。

操作符节点的左子节点和右子节点分别表示运算符的两个操作数,而操作数节点则不包含任何子节点。

通过这种方式,可以将算术表达式表示为一个二叉树结构。

三、算术表达式二叉树的构建1. 中缀表达式转换为后缀表达式为了构建算术表达式的二叉树,首先需要将中缀表达式转换为后缀表达式。

中缀表达式是人们常见的形式,例如"2 + 3 * 5",而后缀表达式则更适合计算机处理,例如"2 3 5 * +"。

将中缀转后缀的算法即为中缀表达式的后缀转换法则。

2. 后缀表达式构建二叉树构建二叉树的过程通常采用栈来辅助完成。

从左到右扫描后缀表达式,对于每个元素,如果是操作数,则入栈;如果是操作符,则弹出栈顶两个元素作为其左右子节点,然后将操作符节点入栈。

最终栈中只剩一个节点,即为构建的二叉树的根节点。

四、算术表达式二叉树的求值算术表达式二叉树的求值是递归进行的。

对于二叉树的每个节点,如果是操作符节点,则递归求解其左右子节点的值,并进行相应的操作;如果是操作数节点,则直接返回其值。

最终得到根节点的值,即为整个算术表达式的值。

五、应用举例以中缀表达式"2 + 3 * 5"为例,首先将其转换为后缀表达式"2 3 5 * +",然后根据后缀表达式构建二叉树,最终求得二叉树的根节点即为算术表达式的值。

四则运算表达式求值(栈+二叉树-c++版)

四则运算表达式求值(栈+二叉树-c++版)

HUNAN UNIVERSITY 课程实习报告题目:四则运算表达式求值学生:周华毅学生学号:201308010411专业班级:计科1304 指导老师:吴帆完成日期:2015/5/1一、需求分析a)四则运算表达式求值,将四则运算表达式用中缀表达式表示,然后转换为后缀表达式,并计算结果。

b)本程序要求利用二叉树后序遍历来实现表达式的转换,同时可以使用实验2的结果来求解后缀表达式的值。

c)在字符界面上输入一个中缀表达式,回车表示结束。

如果该中缀表达式正确,那么在字符界面上输出其后缀表达式,其中后缀表达式中两相邻操作数之间利用空格隔开;如果不正确,在字符界面上输出表达式错误提示。

d)测试数据输入:21+23*〔12-6〕输出:21 23 12 6 -*+二、概要设计抽象数据类型为实现上述程序的功能,应以字符串存储用户的输入,以及计算出的结果。

算法的基本思想根据题目要求,利用二叉树后序遍历来实现表达式的转换。

该算法的基本模块包括二叉树的建立以及如何把输入的中缀表达式利用二叉树后序遍历转化为后缀表达式。

1、首先要将输入的中缀表达式〔数字字符〕存入到二叉树中,由于存在两位或者两位以上的数,甚至还有小数,所以考虑用字符型指针存储数字字符和操作符。

2、为了便于将中缀表达式存入二叉树中,在录入中缀表达式后,要进行相应的处理,比方去掉空格符,添加结束标志,如‘=’、‘#’等。

3、中缀表达式存入到二叉树的过程中,要注意处理的顺序,如‘+’、‘-’号的优先级比‘*’、‘/’号的低,当遇到‘*’、‘/’号时,要判断树以上的节点中是否有‘+’、‘-’号,有的话要与其交换位置。

遇到‘〔’时要反复创建二叉树的结点,构建子二叉树,考虑到括号内要处理的步骤可能会较多,可以考虑用递归。

遇到‘〕’时则直接结束此子二叉树的建立。

此外二叉树中叶子结点存储操作数,非叶子结点存储操作码。

4、对创建好的二叉树进行后序遍历,即可得到相应的后缀表达式,实现方法可以用递归的方式,由于后面还要计算表达式的值,故便利的过程中要将结点中得到的数据存入新的字符数组中。

习题课-二叉树

习题课-二叉树

数据结构与算法二叉树部分习题讲解齐荣嵘qrr0831@edx二叉树(上)一棵有510个结点的完全二叉树的高度为多少?(独根树高度为1)答案:根据公式log2510+1可以计算出高度为9在一棵非空二叉树中,若度为0的结点的个数n,度为2的结点个数为m,则有n=________答案: m+1Problem3-1•下列关于二叉树性质的说法正确的有:1.非空满二叉树的结点个数一定为奇数个。

√•结点度为0或2的数目相差12.当一棵完全二叉树是满二叉树时,叶子结点不一定集中在最下面一层。

√•倒数第二层的度都为0或者23.一棵非空二叉树的为空的外部结点数目等于其结点数加1。

√•2*n0+n1=n0+n1+n2+14.非完全二叉树也可以用像完全二叉树那样使用顺序存储结构进行存储。

×5.完全二叉树最多只有最下面的一层结点度数可以小于2。

×倒数第二层6.满二叉树的所有结点的度均为2。

×可能为0Problem3-2下列关于二叉树遍历的说法正确的有:1.只有空二叉树和一个根结点的二叉树这两种二叉树的前序和中序遍历的顺序恰好一样。

ו所有结点左子树为空的二叉树也满足要求2.所有结点左子树为空的二叉树的前序和中序遍历顺序恰好一样。

√3.所有结点右子树为空的二叉树的前序和中序遍历顺序恰好一样。

×4.只有空二叉树和一个根结点的二叉树这两种二叉树的前序和后序遍历的顺序恰好一样。

√•前序为中左右,而后序为左右中,所以缺失左子树或者右子树都不能让两者一样。

5.所有结点左子树为空的二叉树的前序和后序遍历顺序恰好一样。

×6.存在一棵非空二叉树,它的前序、中序和后序遍历都是一样的。

√•只有一个根结点的二叉树满足要求。

•已知一棵树的前序遍历为ABDEGCF,中序遍历为DBGEACF,求这棵树的后序遍历。

•答案:DGEBFCA•已知一棵树的中序遍历为DBGEACF,后序遍历为DGEBFCA,求这棵树的前序遍历。

二叉树各种计算公式总结

二叉树各种计算公式总结

二叉树各种计算公式总结二叉树是一种常见的数据结构,它由一个根节点和最多两个子节点组成。

许多计算问题可以通过对二叉树进行各种操作和遍历来解决。

在本文中,将总结二叉树的各种计算公式。

1.二叉树节点个数:二叉树节点个数的计算公式是N=N1+N2+1,其中N表示二叉树的节点个数,N1表示左子树的节点个数,N2表示右子树的节点个数。

2. 二叉树的高度:二叉树的高度是指从根节点到最远叶子节点的最长路径上的节点数量。

计算二叉树的高度的公式是H = max(H1, H2) + 1,其中H表示二叉树的高度,H1表示左子树的高度,H2表示右子树的高度。

3.二叉树的深度:二叉树的深度是指从根节点到当前节点的路径的长度。

计算二叉树的深度的公式是D=D1+1,其中D表示二叉树的深度,D1表示父节点的深度。

4.二叉查找树:二叉查找树是一种有序二叉树,它要求对于树中的每个节点,左子树的值都小于节点的值,右子树的值都大于节点的值。

在二叉查找树中进行的公式是:-如果目标值等于当前节点的值,则返回当前节点;-如果目标值小于当前节点的值,则在左子树中继续;-如果目标值大于当前节点的值,则在右子树中继续。

5.二叉树的遍历:二叉树的遍历是指按照一定的顺序访问二叉树中的所有节点。

常见的二叉树遍历方式有三种:- 前序遍历:先访问根节点,然后递归地访问左子树,最后递归地访问右子树。

可以表示为:root -> 左子树 -> 右子树。

- 中序遍历:先递归地访问左子树,然后访问根节点,最后递归地访问右子树。

可以表示为:左子树 -> root -> 右子树。

- 后序遍历:先递归地访问左子树,然后递归地访问右子树,最后访问根节点。

可以表示为:左子树 -> 右子树 -> root。

6.二叉树的最大路径和:二叉树的最大路径和是指二叉树中两个节点之间路径上的节点值的最大和。

可以通过递归地计算每个子树的最大路径和,然后选择最大的子树路径和来得出最终结果。

二叉树的表达式求值

二叉树的表达式求值

⼆叉树的表达式求值问题描述: 输⼊⼀个表达式(表达式中的数均为⼩于10的正整数),利⽤⼆叉树来表⽰该表达数,创建表达式树,然后利⽤⼆叉树的遍历操作求表达式的值。

输⼊要求: 多组数据,每组⼀⾏,以‘=’结尾。

当输⼊只有⼀个‘=’时,输⼊结束。

输出要求: 每组数据输出⼀⾏为表达式的值。

样例: 输⼊样例: 1+2-3*4+(1+2)*3= = 输出样例: 0 思路:分别⽤num 队列来存数,op队列来存运算符。

然后取⼀个运算符为⽗节点,取两个数为⼦结点。

将数叠加后就组成了⼀颗表达式树,然后后序遍历求值即可。

#include<iostream>#include<stack>#include<queue>using namespace std;typedef struct Node* BinTree;typedef BinTree BT;// 1+2-3*4+(1+2)*3=string s;queue<char> num;queue<char> op;struct Node{char Data;BT Left;BT Right;int ans;};int fact(char c) {if (c >= '0' && c <= '9') return1;else return2;}BT createNode(char c){BT p = new Node;p->Data = c;p->Left = p->Right = NULL;if (fact(c) == 1)p->ans = c - '0';elsep->ans = 0;return p;}BT createTree() {BT createTree() {for (int i = 0; i < s.size() - 1; i++) {if(fact(s[i]) == 1) num.push(s[i]);else op.push(s[i]);}BT Head = NULL;int flag = 0; //标记有括号时的情况int sflag = 0; //处理开始时为括号的情况if(s[0] == '(') sflag = 1;while(!op.empty()) {char option;option = op.front(); op.pop();if (option != '(' && option != ')') {BT T = createNode(option);if (option == '+' || option == '-') {if (flag == 0) {if (Head == NULL) {T->Left = createNode(num.front());num.pop();T->Right = createNode(num.front());num.pop();}else {T->Left = Head;T->Right = createNode(num.front());num.pop();}Head = T;}else {if (Head == NULL) {T->Left = createNode(num.front());num.pop();T->Right = createNode(num.front());num.pop();Head = T;}else {T->Left = Head->Right ;Head->Right = T;T->Right = createNode(num.front());num.pop();}}}else if(option == '*' || option == '/') {if (flag == 0) {if(Head == NULL) {T->Left = createNode(num.front());num.pop();T->Right = createNode(num.front());num.pop();Head = T;}else {if(sflag == 1 || Head->Data == '*' || Head->Data == '/') { T->Left = Head;Head = T;T->Right = createNode(num.front());num.pop();sflag =0;sflag =0;}else {T->Left = Head->Right ;Head->Right = T;T->Right = createNode(num.front());num.pop();}}}if (flag == 1) {if(Head == NULL) {T->Left = createNode(num.front());num.pop();T->Right = createNode(num.front());num.pop();Head = T;}else {T->Left = Head->Right; Head->Right= T; T->Right = createNode(num.front());num.pop();}}}}else if (option == '('){flag = 1;//continue;}else if (option == ')'){flag = 0;//continue;}}return Head;}void InorderTraversal_1(BT L){if(L){InorderTraversal_1(L->Left );printf("%d ",L->ans );InorderTraversal_1(L->Right );}}void solve(BT L){if(L){solve(L->Left );solve(L->Right );char option = L->Data ;if (option == '+') L->ans = L->Left->ans + L->Right->ans ;if (option == '-') L->ans = L->Left->ans - L->Right->ans ;if (option == '*') L->ans = L->Left->ans * L->Right->ans ;if (option == '/') L->ans = L->Left->ans / L->Right->ans ;//if(option < '0' || option > '9')// printf("%d %c %d = %d\n", L->Left->ans, option, L->Right->ans, L->ans ); }}}void InorderTraversal_2(BT L){BT T=L;stack<BinTree> s;while(T||!s.empty()){while(T){s.push(T);T=T->Left ;}T=s.top();s.pop();printf("%c ",T->Data );T=T->Right ;}}int main() {while(cin >> s && s[0] != '='){BT H = createTree();//InorderTraversal_2(H);//cout << endl;solve(H);//InorderTraversal_1(H);//cout << endl;cout << H->ans << endl;}} 可能我写的过于复杂,有同学做的⽐较好 。

表达式转表达式二叉树

表达式转表达式二叉树

表达式转表达式⼆叉树表达式树⼆叉树是表达式处理的常⽤⼯具,例如,a+b*(c-d)-e/f可以表⽰成如下所⽰的⼆叉树其中,每个⾮叶⼦节点表⽰⼀个运算符,左⼦树是第⼀个运算数对应的表达式,右⼦树是第⼆个表达式对应的表达式。

每个叶⼦节点都是数。

其在空间利⽤上也⾮常⾼效,节点数等于表达式的长度。

表达式转⼆叉树lrj说⽅法有很多种,下⾯介绍他讲的⼀种:找到“最后计算”的运算符(它是整个表达式树的根),然后递归处理左右两边。

1const int maxn = 1000 + 10;2char str[maxn];3int lch[maxn + 1], rch[maxn + 1]; char op[maxn + 1]; //每个结点的左右⼦结点编号和字符4int nc = 0; //结点数5int build_tree(char* s, int x, int y)6{7int i, c1=-1, c2=-1, p=0;8int u;9if(y-x == 1) //仅⼀个字符,建⽴单独结点10 {11 u = ++nc;12 lch[u] = rch[u] = 0;13 op[u] = s[x];14return u;15 }1617for (i = x; i < y; i++) //寻找根节点的位置18 {19switch (s[i])20 {21case'(': p++; break;22case')': p--; break;23case'+':24case'-': if (!p) c1 = i; break;25case'*':26case'/': if (!p) c2 = i; break;27 }28 }29if (c1 < 0) c1 = c2; //找不到括号外的加减号,就⽤乘除号30if(c1 < 0) return build_tree(s, x+1, y-1); //整个表达式被⼀对括号括起来31 u = ++nc;32 lch[u] = build_tree(s, x, c1);33 rch[u] = build_tree(s, c1+1, y);34 op[u] = s[c1];35return u;36 }前缀式、中缀式、后缀式前缀表达式和后缀表达式分别对应表达式树前序和后序遍历的结果,如果不考虑括号,中缀表达式对应表达式树中序遍历的结果。

基于二叉树的表达式求值算法

基于二叉树的表达式求值算法

基于二叉树的表达式求值算法二叉树的表达式求值算法可以使用递归来实现,具体步骤如下:1. 若该节点为数字节点,则直接返回节点的值;2. 若该节点为操作符节点,则递归计算其左右子树的值,并根据操作符进行计算,最终返回计算结果。

所以,我们可以先构建一个二叉树,然后对二叉树进行递归遍历,实现表达式的求值。

具体实现如下:pythonclass TreeNode:def __init__(self, val):self.val = valself.left = Noneself.right = Nonedef evaluate(root: TreeNode) -> int:"""对二叉树进行递归遍历,实现表达式的求值"""# 如果当前节点为数字,直接返回节点的值if not root.left and not root.right:return int(root.val)# 递归计算左子树的值和右子树的值left_val = evaluate(root.left)right_val = evaluate(root.right)# 根据运算符计算当前节点的值if root.val == '+':return left_val + right_valelif root.val == '-':return left_val - right_valelif root.val == '*':return left_val * right_valelse:return left_val right_val这里假设输入的二叉树是合法的,即括号、运算符和操作数的顺序都正确,不需要进行错误处理。

二叉树表达式求值

二叉树表达式求值

一、程序设计的基本思想,原理和算法描述:表达式建树原理:对表达式先找到运算级最低的运算操作符,并将其作为该表达式的根结点,该运算符左右两段表达式分别作为其左右子树。

1.若该运算操作符位于表达式首,则其一定是“-”,此时左子树为空;2.若该运算操作符是一对括弧(括弧嵌套情况)则化简(把括弧去掉),对表达式构造二叉树;表达式不合法情况:1.表达式首为:“+”、“*”、“/”、“.”、“)”;2.表达式尾为:“+”、“-”、“*”、“/”、“.”、“(”;表达式合法情况:1.表达式非首位置:a.“(”之前只能为:“+”、“-”、“*”、“/”、“(”;b.“)”之前只能为:“)”、数字“0-9”;c.“+”、“*”、“/”之前只能为:“)”、数字“0-9”;d.“-”之前只能为:“(”、“)”、数字“0-9”;e.“.”之前只能为:数字“0-9”;表达式求值:将操作数全部转化为double数据类型进行求解。

测试数据:1. -((2.5+2.5)/(3-1)*4+(10-8)*6)/(4-2)+(-2*(4+1)/(3-1)*2+1)+12. -((((3-1)/2+2.5-(3-4+6))/2 -3*2/1)+1.5)*2-3*3/2/(5-3)3. 1000000000*2000000000/44. 200.3.3*32.15. 99999/116. (45-33)*2-3+4/2*5-37. -(45-33)*2-3+4/2*5-3二、源程序及注释://ExpnBiTree.cpp#include<stdio.h>#include<string.h>#include<stdlib.h>#define STATUS int#define OK 1#define ERROR 0#define EXP_LEN 100 //定义表达式的最大长度#define DATA_LEN 20 //定义每个操作数的最大长度typedef struct BinaryTree{int dflag; //标志域,值为1,data[]存放操作运算符;值为0,data[]存放操作数char data[DATA_LEN+1]; //数据域,存放:操作运算符或操作数struct BinaryTree *lchild,*rchild; //分别指向结点的左、右子树}BiTNode,*BiTree; //定义二叉树结点及二叉树类型指针STATUS CreateBiTree(BiTree &bt,char *p,int l);//创建二叉树,并用bt返回树的根地址,p为表达式的首地址,l为表达式的长度STATUS Calculate(BiTree bt,double &rst);//计算表达式的值,bt为据表达式创建的二叉树,用rst返回表达式的值STATUS PreOrderTraverse(BiTree bt); //先序遍历二叉树bt,输出先序遍历序列STATUS InOrderTraverse(BiTree bt); //中序遍历二叉树bt,输出中序遍历序列STATUS PostOrderTraverse(BiTree bt); //后序遍历二叉树bt,输出后序遍历序列STATUS DestroyBiTree(BiTree &bt); //销毁二叉树void main(){int n,l,i; //n标志量,值为0,退出程序;l存储表达式的长度;i一般变量char expn[EXP_LEN+1]; //存放表达式double rst; //存放表达式计算结果BiTree bt=NULL; //声明一个二叉树do{i=0;printf("请输入合法的表达式:\n");gets(expn);for(i=0,l=0;expn[i]!='\0';i++) //去掉表达式中的空格,并计算表达式的长度if(expn[i]!=' ')expn[l++]=expn[i];expn[l]='\0';printf("正在构建二叉树……\n");if(CreateBiTree(bt,expn,l))printf("二叉树构建成功!\n");else{ //销毁未成功建立的二叉树,释放动态申请的内存printf("二叉树构建失败!\n");printf("将销毁二叉树………… ");if(DestroyBiTree(bt)) printf("二叉树销毁成功!\n");else {printf("二叉树销毁失败!\n");exit(0);}continue;}printf("即将输出表达式的先序遍历序列……:\n");PreOrderTraverse(bt);printf("\n");printf("即将输出表达式的中序遍历序列……:\n");InOrderTraverse(bt);printf("\n");printf("即将输出表达式的后序遍历序列……:\n");PostOrderTraverse(bt);printf("\n");printf("正在计算表达式的值……:\n");if(Calculate(bt,rst))printf("%g\n",rst);else printf("计算表达式的值失败!\n");printf("即将销毁二叉树…………");if(DestroyBiTree(bt)) printf("二叉树销毁成功!\n");else {printf("二叉树销毁失败!\n");exit(0);}printf("如果要继续计算下一个表达式,请输入一个非零整数,否则,请输入0: ");scanf("%d",&n); getchar();}while(n);}STATUS CreateBiTree(BiTree &bt,char *p,int l){int i=0,lnum=0,rpst1=-1,rpst2=-1,pn=0;//lnum记录"("的未成对个数;//rpst1/rpst2记录表达式中优先级最低的("*"、"/")/("+"、"-")的位置; //pn记录操作数中"."的个数,以判断输入操作数是否合法if(l==0)return OK;if(!(bt=(BiTree)malloc(sizeof(BiTNode)))){printf("内存申请失败\n");return ERROR;}else{bt->lchild=bt->rchild=NULL;memset(bt->data,'\0',sizeof(bt->data));bt->dflag=1;//默认bt为叶子节点(即,存放操作数)if(*p=='+'||*p=='*'||*p=='/'||*p=='.'||*p==')') //表达式首不合法;{printf("表达式输入错误!\n"); return ERROR;}if(!(*(p+l-1)==')'||*(p+l-1)>='0'&&*(p+l-1)<='9')) //表达式尾不合法;{printf("表达式输入错误!\n"); return ERROR;}}if(l==1) //此时只有表达式为数字,表达式才合法if(*p<'0'||*p>'9'){printf("表达式输入错误!\n"); return ERROR;} else {bt->data[0]=*p;return OK;}else if(l==2) //此时只有表达式为正数或负数,表达式才合法if((*p=='-'||*p>='0'&&*p<='9')&&*(p+1)>='0'&&*(p+1)<='9'){bt->data[0]=*p;bt->data[1]=*(p+1);return OK;}else{printf("表达式输入错误!\n"); return ERROR;}else{if(*p=='(')lnum++;for(i=1;i<l;i++){if(*(p+i)=='.'){if(!(*(p+i-1)>='0'&&*(p+i-1)<='9')){printf("表达式输入错误!\n"); return ERROR;}}else if(*(p+i)=='*'||*(p+i)=='/'){if(!(*(p+i-1)>='0'&&*(p+i-1)<='9'||*(p+i-1)==')')){printf("表达式输入错误!\n"); return ERROR;}if(lnum==0)rpst1=i;}else if(*(p+i)=='('){if(*(p+i-1)=='+'||*(p+i-1)=='-'||*(p+i-1)=='*'||*(p+i -1)=='/'||*(p+i-1)=='(')lnum++;else{printf("表达式输入错误!\n"); return ERROR;}}else if(*(p+i)==')'){if(*(p+i-1)==')'||*(p+i-1)>='0'&&*(p+i-1)<='9')lnum--; else{printf("表达式输入错误!\n"); return ERROR;}if(lnum<0){printf("表达式输入错误!\n"); return ERROR;} }else if(*(p+i)=='+'||*(p+i)=='-'){if(*(p+i)=='+'&&!(*(p+i-1)>='0'&&*(p+i-1)<='9'||*(p+i -1)==')')){printf("表达式输入错误!\n"); return ERROR;}else if(*(p+i)=='-'&&!(*(p+i-1)>='0'&&*(p+i-1)<='9'||*(p+i-1)==')'||*(p+i-1)=='(')){printf("表达式输入错误!\n"); return ERROR;}if(lnum==0)rpst2=i;}}if(lnum!=0){printf("表达式输入错误!\n"); return ERROR;}//"("、")"未能完全配对,表达式输入不合法if(rpst2>-1){bt->dflag=0;bt->data[0]=*(p+rpst2);if(CreateBiTree(bt->lchild,p,rpst2))if(CreateBiTree(bt->rchild,p+rpst2+1,l-rpst2-1))return OK;return ERROR;}if(rpst1<0)//此时表明表达式或者是一个数字,或是表达式整体被一对括弧括起来{if(*p=='(') //此时表达式整体被一对括弧括起来if(CreateBiTree(bt,p+1,l-2))return OK;else return ERROR;else{if(*(p+1)!='(') //此时表达式一定是一个数字{for(i=0;i<l;i++){if(*(p+i)=='.')pn++;if(pn>1){printf("表达式输入错误!\n"); return ERROR;}bt->data[i]=*(p+i);}return OK;}else //此时表达式首一定是操作符"-",其余部分被一对括弧括起来{bt->dflag=0;bt->data[0]='-';if(CreateBiTree(bt->rchild,p+2,l-3))return OK;else return ERROR;}}}else //此时表明表达式为几个因子想成或相除而组成的{bt->dflag=0;bt->data[0]=*(p+rpst1);if(CreateBiTree(bt->lchild,p,rpst1))if(CreateBiTree(bt->rchild,p+rpst1+1,l-rpst1-1))retur n OK;return ERROR;}}}STATUS Calculate(BiTree bt,double &rst){double l=0,r=0;//l、r分别存放左右子树所代表的字表达式的值if(!bt){rst=0;return OK;}if(bt->dflag==1){rst=atof(bt->data);return OK;}else{if(Calculate(bt->lchild,l))if(Calculate(bt->rchild,r)){switch(bt->data[0]){case '+' : rst=l+r;break;case '-' : rst=l-r;break;case '*' : rst=l*r;break;case '/' : if(r==0){printf("除数为0 !\n");return ERROR;}else{rst=l/r;break;}default : return ERROR;}//printf("%g%c%g=%g\n",l,bt->data[0],r,rst);//输出运算过程return OK;}return ERROR;}}STATUS PreOrderTraverse(BiTree bt){if(bt){printf("%s ",bt->data);if(PreOrderTraverse(bt->lchild))if(PreOrderTraverse(bt->rchild))return OK;return ERROR;}return OK;}STATUS InOrderTraverse(BiTree bt){if(bt){if(InOrderTraverse(bt->lchild)){printf("%s ",bt->data);if(InOrderTraverse(bt->rchild))return OK;return ERROR;}return ERROR;}return OK;}STATUS PostOrderTraverse(BiTree bt){if(bt){if(PostOrderTraverse(bt->lchild))if(PostOrderTraverse(bt->rchild)){printf("%s ",bt->data);return OK;}else return ERROR;}return OK;}STATUS DestroyBiTree(BiTree &bt){if(bt){if(DestroyBiTree(bt->lchild))if(DestroyBiTree(bt->rchild)){free(bt);return OK;}else return ERROR;}return OK;}三、心得与体会:在考虑建树的如何建树过程中,思考了很长时间,通过和同学交流,把表达式可能出现的各种情况都注意到,使得建树函数对各种表达式都适用(括弧嵌套,并列)。

先序遍历表达式求值

先序遍历表达式求值

先序遍历表达式求值
摘要:
1.先序遍历表达式的概念
2.先序遍历表达式的求值方法
3.先序遍历表达式的应用实例
正文:
先序遍历表达式求值是计算机科学中的一种算法,主要用于计算二叉树中表达式的值。

先序遍历是指按照“根- 左-右”的顺序遍历二叉树。

在遍历过程中,我们可以通过对表达式中各个部分的求值,最终得到整个表达式的值。

求值方法如下:
1.首先,我们需要遍历二叉树的根节点,并将其值存储在一个变量中。

2.接下来,我们需要遍历左子树,并将遍历到的值与根节点的值进行运算(如加法、减法等),将结果存储在另一个变量中。

3.然后,我们需要遍历右子树,并将遍历到的值与上一步的结果进行运算,得到最终的表达式值。

在实际应用中,先序遍历表达式求值常用于计算二叉树中复杂表达式的值。

例如,给定一个二叉树,其根节点的值为5,左子树的值为3,右子树的值为2,我们可以通过先序遍历表达式求值得到该二叉树表示的表达式值为(5+3)*2=16。

总之,先序遍历表达式求值是一种有效的计算二叉树中复杂表达式值的方法。

通过按照“根- 左-右”的顺序遍历二叉树,并对表达式中各个部分进行
求值和运算,我们可以得到整个表达式的值。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{
switch(str1)
{
case '#':case'(':case'[':return 0;break;
case '*':case '/':return 1;break;
case '+':case'-':switch(str2)
{
case '+':case'-':case'#':return 1;break;
}
pushstack1(L1,p[i]);
break;
}
}
i++;
}
popstack2(L2,T);
return T;
}
//后序遍历表达式树
void postorder(BiTree T)
{
if(T)
{
postorder(T->lchild);
printf("后缀式为:");
postorder(T);
printf("\n");
printf("前缀式为");
midorder(T);
printf("\n");
printf("结果为:");
printf("%.3f\n",T->data2);
}
{
while(indigit(p[i]))
{
str[j++]=p[i];
i++;
}
str[j]='\0';
createleaf(T,str,L2);
j=0; i--;
}
else
{
switch(p[i])
L.data[L.top]=T;
return 1;
}
int popstack2(seqstack2 &L,BiTree &T)
{
if(L.top==-1)
{ printf("?空栈!\n"); return 0;}
T=L.data[L.top];
L.top--;
return 1;
postorder(T->rchild);
printf("%s ",T->data1);
}
}
//先序遍历表达式树
void midorder(BiTree T)
{
if(T)
{
midorder(T->lchild);
printf("%s ",T->data1);
}
float calculate(float a,float b,char *ch)
{
if(strcmp(ch,"*")==0)
return (a*b);
else if(strcmp(ch,"/")==0)
return (a/b);
else if(strcmp(ch,"+")==0)
printf("!!空栈!\n");
else
return L.data[L.top];
}
//操作数栈
int initstack2(seqstack2 &L)
{
L.data=(BiTree *)malloc(max * sizeof(BiTree));
if(L.data==NULL) exit(0);
case '*':case '/':return 0;break;
}break;
}
}
int indigit(char ch)
{
if(ch>='0'&&ch<='9'||ch=='.')
return 1;
else
return 0;
}
//建子叶
void createleaf(BiTree &T,char *ch,seqstack2 &L2)
{
float n;
T=(Bnode *)malloc(sizeof(Bnode));
if(T==NULL) exit(0);
n=transform(ch);
{
result1=result1*10+ch[i]-'0';
i++;
}
if(ch[i]=='\0')
return result1;
else
{
while(ch[i]!='\0')
{
str[k]=ch[i];
k++;i++;
}
str[k]='\0';
//二叉树上的表达式求值算法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define max 100
typedef struct
{
char *data;
int top;
int stacksize;
}seqstack1;
int i=0,j=0;
BiTree T,lchild,rchild;
char str[20],ch;
initstack1(L1); pushstack1(L1,'#'); initstack2(L2);
while(p[i]!='\0')
{
if(indigit(p[i]))
}
int gettop2(seqstack2 L,BiTree &T)
{
if(L.top==-1)
{ printf("空栈!\n"); return 0;}
T=L.data[L.top];
return 1;
}
//求值栈
int prior(char str1,char str2)
int stacksize;
}seqstack2;
//运算符栈
int initstack1(seqstack1 &L)
{
L.data=(char *)malloc(max * sizeof(char));
if(L.data==NULL) exit(0);
L.top=-1;
return (a+b);
else
return (a-b);
}
float transform(char *ch)
{
float result=0,result1=0,result2=0;
char str[20];
int i=0,k=0;
while(ch[i]>='0'&&ch[i]<='9')
strcpy(T->data1,ch);
T->data2=n;
T->lchild=T->rchild=NULL;
pushstack2(L2,T);
}
//建子树
void createtree(BiTree &T,char *ch,BiTree rchild,BiTree lchild,seqstack2 &L2)
{
case '(':case '[':pushstack1(L1,p[i]);break;
case ')':ch=popstack1(L1);
while(ch!='(')
{
createtree(T,&ch,rchild,lchild,L2);
{
float n;
ch[1]='\0';
T=(Bnode *)malloc(sizeof(Bnode));
if(T==NULL) exit(0);
popstack2(L2,rchild);
popstack2(L2,lchild);
n=calculate(lchild->data2,rchild->data2,ch);
ch=popstack1(L1);
}
break;
default:
ch=gettop1(L1);
while(prior(ch,p[i]))
{
createtree(T,&ch,rchild,lchild,L2);
ch=popstack1(L1); ch=gettop1(L1);
midorder(T->rchild);
}
}
void main()
{
char *p;
BiTree T;
p=(char *)malloc(max * sizeof(char));
printf("输入表达式(以#号结束):");
相关文档
最新文档