描述

输入一个表达式(表达式中的数均为小于10的正整数),利用二叉树来表示该表达式,创建表达式树,然后利用二叉树的遍历操作求表达式的值。

输入

多组数据。每组数据一行,为一个表达式,表达式以‘=’结尾。当输入只有一个“=”时,输入结束。

输出

每组数据输出一行,为表达式的值。

输入样例 1

2*(2+5)=
1+2=
=

输出样例 1

14

思路:

以前用栈做的时候思路是为运算符建立一个栈,为运算数建立一个栈,根据运算输入输出。这次是用树做,仍然涉及到数的弹栈,但是这个数是存储在Tree节点里的,每一个节点都可能存储数字,也可能存储字符,所以仍然是两个栈,一个存运算符,另一个不再存数字而是存一个Tree节点,方便建立树。

我做的时候感觉这个题的主要问题就是建立的树是在哪里建立的和怎么找到根节点。主函数里面肯定会初始化一棵空树,那么是遇到一个节点就用它建立树吗?如果它是叶子节点怎么办呢?有好多问题都是非常糊涂的,甚至根本不知道怎么用语言描述。

Build函数是遍历并建立树的过程。一开始用的是string接收,再逐个遍历字符去进行相应操作,但是不行,后来全都大改了,因为for遍历完整个算式并不意味着树就已经建立好了,可以想到如果是数值之间需要运算,或者运算的结果需要储存的话,这棵树还需要不断建立,直到没有任何结果需要被添加进树为止,而string遍历的方式无法知道这个过程什么时候结束,所以只能逐个输入字符每次都判断。

RUOptr函数是判断当前位置字符是否是运算符的。

CreateTree函数是用来创建树的。这里即将解决一个大问题:主函数用来输出的那个最终的btree是不是要进这个函数被创建?答案是不用,它不是CreateTree的目标对象,也就是说,CreateTree实际上是用当前字符在自己的函数里面创建了一个节点,连带着它的两个子节点的值一起被创建了,并返回这个节点,后续还会对这个节点进行处理。因为我们主函数里那个树必须是最终建成的那棵树的根节点,而不能随随便便就和别的某一个节点相等;同时,这个创建树的算法不是递归!!!想一想,不知道下一个节点是什么(数or符),从而不知道下一个节点和它的关系;也不知道自己的位置,这怎么递归?不要被ppt和课本框住了,更不要照着上面的代码硬抄。。。教训实在惨痛。。。

现在我们拥有了一个包含一个数字的节点,该怎么做呢?答案是:不知道怎么做。因为单纯的数字节点毫无意义,只有遇到运算符才能和其他数字节点产生运算关系,并以运算符为中心形成一棵小型的树,所以现在它没用,先入栈,千万别把主函数的btree给赋值!!

之后再次判断下一个字符,cmp是用来比运算符优先级的函数。要是运算符就和以前一样,比栈顶存的优先级高就入栈,要是')'或者'='就出栈,相等(可以运算)是重点!!这个时候从树节点栈里面弹出来两个数做运算,由于遇到了运算符,那么CreateTree,temp的op给它,左右孩子也都知道了(刚才弹出来的两个数),这样就相当于建立了一个小树。这个时候注意:我们主函数里那个btree可以被赋值了!举个例子,如果是1+2=这样的式子,现在已经算完了,bt应该就指向那个+对吧,所以推广一下,每次建立的这个root才是btree应该=的。

Calculate和Operate就是遍历树去计算的过程,这个时候可以递归了,因为树已经建立起来了。

感觉这题超过我目前水平。。希望这篇文章能让自己明白,也能让读者明白吧。。

代码:

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
using namespace std;typedef struct BNode
{int num;char op;struct BNode* lchild, * rchild;
}*BTree, BNode;
typedef struct TreeNode
{BTree data;struct TreeNode* next;
}*Tstack, TNode;
typedef struct OptrNode
{char optr;struct OptrNode* next;
}*Ostack, ONode;
char PopNoPrint(Ostack& os)
{if (os){char temp = os->optr;Ostack t = os;os = os->next;delete t;//不打印,返回值return temp;}
}
char TOP(Ostack os)
{if (os)    return os->optr;
}
BTree PopNoPrint(Tstack& ts)//把返回值改成了BTree
{if (ts){BTree temp = ts->data;Tstack t = ts;ts = ts->next;delete t;//不打印,返回值return temp;}
}
void InitStack(Ostack& os,Tstack& ts)
{os = NULL;ts = NULL;
}
BTree CreateTree(char c, BTree& l, BTree& r)
{//改了,不是bt = new BNode;BTree temp = new BNode;temp->op = c;temp->lchild = l;temp->rchild = r;return temp;
}
BTree CreateTree(int a, BTree& l, BTree& r)
{//改了,不是bt = new BNode;BTree temp = new BNode;temp->num = a;temp->lchild = l;temp->rchild = r;return temp;
}
void InStack(Ostack& os,char c)//运算符入栈
{Ostack temp = new ONode;temp->optr = c;temp->next = NULL;temp->next = os;os = temp;
}
void InStack(Tstack& ts, BTree bt)//树入栈
{Tstack temp = new TNode;temp->data = bt;temp->next = ts;ts = temp;
}
int RUOptr(char ch) //判断读入的字符ch是否为运算符
{if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')' || ch == '=')return true;else return false;
}
int cmp(char a,char b)//比较运算符优先级
{if (a == '*' || a == '/'){if (b == '(')return -1;elsereturn 1;}if (a == '+' || a == '-'){if (b == '*' || b == '/' || b == '(')return -1;elsereturn 1;}if (a == '(')if (b == ')')return 0;else return -1;if (a == '=')if (b == '=')return 0;elsereturn -1;else return 1;
}
int Operate(int a, char theta, int b)
{switch (theta){case '+':return a + b; break;case '-':return a - b; break;case '*':return a * b; break;case '/':return a / b; break;default:break;}
}
int Calculate(BTree bt)
{if (!bt)return 0;if (!bt->lchild && !bt->rchild){    //左右子树都为空,说明该节点是个数,需要运算return bt->num;}else{int lvalue=0, rvalue=0;lvalue = Calculate(bt->lchild);rvalue = Calculate(bt->rchild);return Operate(lvalue, bt->op, rvalue);}
}
void Build(BTree& bt)
{Tstack t;Ostack o;InitStack(o, t);InStack(o, '=');char c;cin >> c;if (c == '=')exit(0);while (TOP(o) != '='||c!='='){if (!RUOptr(c))//不是运算符{BTree temp = NULL;//这句!InStack(t, CreateTree(c-'0', temp, temp));cin >> c;}else//是运算符{if (cmp(TOP(o), c)==-1)//优先级高于当前字符{InStack(o, c);//入栈cin >> c;}else if(cmp(TOP(o),c)==1)//弹符弹数做运算后入栈{   //这里若能加以改进……BTree x = new BNode, y = new BNode;x = PopNoPrint(t), y = PopNoPrint(t);BTree root = CreateTree(PopNoPrint(o), x, y);InStack(t, root);bt = root;}else//是'=',说明一个是'('一个是')'{PopNoPrint(o);//'('出栈cin >> c;}}}
}int main()
{while (1){BTree b;Build(b);cout << Calculate(b) << endl;}return 0;
}

3011-基于二叉树的表达式求值(C++,附详细思路)相关推荐

  1. 表达式求值(最详细分析+代码实现+表达式之间的相互转换)

    目录 一.概念 二.前缀表达式的逻辑和实现方式 1.定义 2.前缀表达式的计算机求值 3.例子 4.代码实现 三.中缀表达式的逻辑和实现方式 1.定义 2.中缀表达式规则 3.中缀表达式的计算机求值 ...

  2. leetcode_150. 逆波兰表达式求值

    一.题目内容 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.* ./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除法只保留整数部分. 给定逆波兰表达式总是有效的 ...

  3. 数据结构—— 基于二叉树的算术表达式求值

    实验五 基于二叉树的算术表达式求值 数据结构--中序表达式求值(栈实现) 实验目的: 1.掌握二叉树的二叉链表存储表示和二叉树的遍历等基本算法. 2.掌握根据中缀表达式创建表达式树的算法 3.掌握基于 ...

  4. php表达式求值,PHP实现基于栈的后缀表达式求值功能

    本文实例讲述了PHP实现基于栈的后缀表达式求值功能.分享给大家供大家参考,具体如下: 后缀表达式概述 后缀表达式,指的是不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左 ...

  5. c语言中缀表达式求值_[源码和文档分享]基于C++的表达式计算求值

    一.使用说明 1.1 项目简介 表达式求值是程序设计语言编译中的一个最基本的问题,就是将一个表达式转化为逆波兰表达式并求值.具体要求是以字符序列的形式从终端输入语法正确的.不含变量的整数表达式,并利用 ...

  6. C++代码实现中缀表达式求值(基于中缀表达式转后缀表达式)

    C++代码实现中缀表达式求值(基于中缀表达式转后缀表达式) 样例输入:3*(2+5) 样例输出:21 代码:#include <bits/stdc++.h> using namespace ...

  7. 北京林业大学数据结构实验二 基于栈的算术表达式求值算法

    第1关:基于栈的中缀算术表达式求值 参见课本P75 例3.3 #include <iostream> #include<iomanip>#define MAXSIZE 100 ...

  8. 基于栈的后缀表达式求值(洛谷P1449题题解,Java语言描述)

    题目要求 P1449题目链接 分析 给出后缀表达式求值,就相当于没了括号,而且很直接. 我们需要使用栈结构来完成任务. Java原装的栈使用了很多synchronized,导致性能不佳,但我们也就将就 ...

  9. 【Java】基于栈的算术表达式求值

    定义异常类 public class ExpressionException extends RuntimeException {private static final long serialVer ...

最新文章

  1. ★ 省时省力又省钱--快来看win7家庭版升级旗舰版 ★
  2. matlab simulink互感,Simulink互感模块用set_param函数不能正确赋值
  3. 黑马程序员:从零基础到精通的前端学习路线
  4. 【公司金融课堂学习笔记】2、企业融资—风投如何影响企业价值
  5. codeforces 919E Congruence Equation
  6. 产品经理经验谈100篇(四)-B端交互设计规范
  7. 地质灾害防治条例释义的摘要
  8. db15接口各针脚示意图_【沙发管家】带你了解 HDMI 接口的用处都有哪些?
  9. 通过 powershell 配置 IIS
  10. bzoj3551 [ONTAK2010]Peaks加强版(Kruskal重构树+主席树)
  11. 通过微信查找SAP TCODE代码
  12. 生产环境和开发环境_生产环境 VS 开发环境,关于Kubernetes的四大认识误区
  13. css设置动画匀速运动,CSS3 transition动画
  14. 中国朝代历史,名字的简介
  15. MySQL——————表的查询
  16. 祛湿不能迷信红豆薏米水!
  17. Java中int的取值范围的原因
  18. 无密码登陆的ssh和ssh-agent
  19. 福建师范大学计算机科学专业,福建师范大学计算机科学与技术专业在哪个校区...
  20. “快来”为你解读视联网发展阶段之婴儿篇

热门文章

  1. JBox2D For Android - hello box2d
  2. python 查看数据结构类型_python 数据结构类型总结(示例代码)
  3. 关于Linux开源项目基础组件make编译流程
  4. 大数据的乘法实现——C语言
  5. hdu 5172 GTY's gay friends(线段树最值)
  6. 使用haskell来解线性方程
  7. Flutter图像绘制原理深入分析
  8. 读《人月神话》有感2
  9. perl6检测网站CMS脚本(测试代码)
  10. 第十周 11.1-11.7