表达式树---中缀表达式变逆波兰表达式
2017-05-02 16:56
176 查看
http://dsalgo.openjudge.cn/binarytree/7/
部分算法, 打印树的内容今后有机会再补上
总时间限制: 1000ms 内存限制: 65535kB
描述
众所周知,任何一个表达式,都可以用一棵表达式树来表示。例如,表达式a+b*c,可以表示为如下的表达式树:
+
/ \
a *
/ \
b c
现在,给你一个中缀表达式,这个中缀表达式用变量来表示(不含数字),请你将这个中缀表达式用表达式二叉树的形式输出出来。
输入
输入分为三个部分。
第一部分为一行,即中缀表达式(长度不大于50)。中缀表达式可能含有小写字母代表变量(a-z),也可能含有运算符(+、-、*、/、小括号),不含有数字,也不含有空格。
第二部分为一个整数n(n < 10),表示中缀表达式的变量数。
第三部分有n行,每行格式为C x,C为变量的字符,x为该变量的值。
输出
输出分为三个部分,第一个部分为该表达式的逆波兰式,即该表达式树的后根遍历结果。占一行。
第二部分为表达式树的显示,如样例输出所示。如果该二叉树是一棵满二叉树,则最底部的叶子结点,分别占据横坐标的第1、3、5、7……个位置(最左边的坐标是1),然后它们的父结点的横坐标,在两个子结点的中间。如果不是满二叉树,则没有结点的地方,用空格填充(但请略去所有的行末空格)。每一行父结点与子结点中隔开一行,用斜杠(/)与反斜杠(\)来表示树的关系。/出现的横坐标位置为父结点的横坐标偏左一格,\出现的横坐标位置为父结点的横坐标偏右一格。也就是说,如果树高为m,则输出就有2m-1行。
第三部分为一个整数,表示将值代入变量之后,该中缀表达式的值。需要注意的一点是,除法代表整除运算,即舍弃小数点后的部分。同时,测试数据保证不会出现除以0的现象。
样例输入
![](https://img-blog.csdn.net/20170502163533882?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWVsYW5pZWVjZA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
样例输出
![](https://img-blog.csdn.net/20170502163614601?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWVsYW5pZWVjZA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
思路:
(1) 用两个栈来做临时存放器: s1 存放操作的项,s2存放运算符号
(2) 存放的规则如下:
遇到字母,直接放进s1
遇到运算符,判断: 如果是+或-,用last=s2.top()来操作 s1顶的两项
如果是* 或 %,判断last = s2.top():
如果last 是 + 或-, 把运算符放进s2, 并进行下一步操作
(3) 处理括号: 左括号放进s2, 等待右括号。 遇到右括号,把s2中做括号之前的所有运算符操作完
(4) 存放完后的后续操作: 存放完表达式,s1、s2中肯定还剩下内容,需要完成剩余内容的收尾
(5) 计算表达式的值:在node 的struct中就需要设置一个int sum, 来记录计算结果。在处理表达式的每一步都把sum计算出来,最终输出root的sum, 就是整个表达式的计算结果。
部分算法, 打印树的内容今后有机会再补上
总时间限制: 1000ms 内存限制: 65535kB
描述
众所周知,任何一个表达式,都可以用一棵表达式树来表示。例如,表达式a+b*c,可以表示为如下的表达式树:
+
/ \
a *
/ \
b c
现在,给你一个中缀表达式,这个中缀表达式用变量来表示(不含数字),请你将这个中缀表达式用表达式二叉树的形式输出出来。
输入
输入分为三个部分。
第一部分为一行,即中缀表达式(长度不大于50)。中缀表达式可能含有小写字母代表变量(a-z),也可能含有运算符(+、-、*、/、小括号),不含有数字,也不含有空格。
第二部分为一个整数n(n < 10),表示中缀表达式的变量数。
第三部分有n行,每行格式为C x,C为变量的字符,x为该变量的值。
输出
输出分为三个部分,第一个部分为该表达式的逆波兰式,即该表达式树的后根遍历结果。占一行。
第二部分为表达式树的显示,如样例输出所示。如果该二叉树是一棵满二叉树,则最底部的叶子结点,分别占据横坐标的第1、3、5、7……个位置(最左边的坐标是1),然后它们的父结点的横坐标,在两个子结点的中间。如果不是满二叉树,则没有结点的地方,用空格填充(但请略去所有的行末空格)。每一行父结点与子结点中隔开一行,用斜杠(/)与反斜杠(\)来表示树的关系。/出现的横坐标位置为父结点的横坐标偏左一格,\出现的横坐标位置为父结点的横坐标偏右一格。也就是说,如果树高为m,则输出就有2m-1行。
第三部分为一个整数,表示将值代入变量之后,该中缀表达式的值。需要注意的一点是,除法代表整除运算,即舍弃小数点后的部分。同时,测试数据保证不会出现除以0的现象。
样例输入
样例输出
思路:
(1) 用两个栈来做临时存放器: s1 存放操作的项,s2存放运算符号
(2) 存放的规则如下:
遇到字母,直接放进s1
遇到运算符,判断: 如果是+或-,用last=s2.top()来操作 s1顶的两项
如果是* 或 %,判断last = s2.top():
如果last 是 + 或-, 把运算符放进s2, 并进行下一步操作
(3) 处理括号: 左括号放进s2, 等待右括号。 遇到右括号,把s2中做括号之前的所有运算符操作完
(4) 存放完后的后续操作: 存放完表达式,s1、s2中肯定还剩下内容,需要完成剩余内容的收尾
(5) 计算表达式的值:在node 的struct中就需要设置一个int sum, 来记录计算结果。在处理表达式的每一步都把sum计算出来,最终输出root的sum, 就是整个表达式的计算结果。
#include <iostream> #include <stack> using namespace std; char suanshi[50]; int val_num[200]; int sum=0; struct node{ public: char val; int sum; node* zuo, * you; }; stack<node*> s1,s2; // s1储存项, s2储存运算符号 node * root; int calculate ( char suan, int s1, int s2){ if (suan=='+') return s1+s2; else if (suan == '-') return s1-s2; else if (suan == '*') return s1*s2; else return s1/s2; } void clear_end(){ while (!s2.empty()){ int sum1, sum2; node* temp = s2.top(); s2.pop(); sum2 = s1.top()->sum; temp->you = s1.top(); s1.pop(); sum1 = s1.top()->sum; temp->zuo = s1.top(); s1.pop(); temp->sum = calculate(temp->val, sum1, sum2); s1.push(temp); } root = s1.top(); //cout<<root->val<<endl; } void push_back_bracket(){ while(s2.top()->val!= '('){ int sum1, sum2; node* last = s2.top(); s2.pop(); sum2 = s1.top()->sum; last->you = s1.top(); s1.pop(); sum1 = s1.top()->sum; last->zuo = s1.top(); s1.pop(); last->sum = calculate(last->val, sum1, sum2); s1.push(last); } s2.pop(); } void push_suanshi(node* tmp_node){ int sum1, sum2; if (!s2.empty() && s2.top()->val!='('){ node* last = s2.top(); s2.pop(); char tmp = tmp_node->val; if (tmp=='*' || tmp == '/'){ // 如果tmp运算符号是*或/ if (last->val=='*' || last->val =='/'){ sum2 = s1.top()->sum; last->you = s1.top(); s1.pop(); sum1 = s1.top()->sum; last->zuo = s1.top(); s1.pop(); last->sum = calculate(last->val, sum1, sum2); s1.push(last); s2.push(tmp_node); } else if (last->val=='+' || last->val=='-'){ s2.push(last); s2.push(tmp_node); } } else if (tmp=='+' || tmp=='-'){ // 如果tmp是+或-,把last计算掉 sum2 = s1.top()->sum; last->you = s1.top(); s1.pop(); sum1 = s1.top()->sum; last->zuo = s1.top(); s1.pop(); last->sum = calculate(last->val, sum1, sum2); s1.push(last); s2.push(tmp_node); } } else s2.push(tmp_node); } void print_tree(node * root){ if (root == NULL) return; print_tree(root->zuo); print_tree(root->you); cout<<root->val; } int main() { cin>>suanshi; int n; char val; int num; cin>>n; for (int i=0; i<n; i++){ cin>>val>>num; val_num[(int)val] = num; //cout<<val_num[(int)val] <<endl; } int length=(int)strlen(suanshi); for (int i=0; i<length; i++){ char tmp= suanshi[i]; node* tmp_node = new node; tmp_node->val = tmp; tmp_node->zuo = tmp_node->you = NULL; if (tmp=='*' || tmp == '/' || tmp=='+' || tmp =='-') push_suanshi(tmp_node); else if (tmp=='(') s2.push(tmp_node); else if (tmp==')') push_back_bracket(); else { tmp_node->sum = val_num[(int)tmp]; //cout<<tmp_node->val << " "<<tmp_node->sum<<endl; s1.push(tmp_node);} } clear_end(); print_tree(root); cout<<endl; cout<<root->sum<<endl; return 0; }
相关文章推荐
- C语言利用栈实现将中缀表达式转换为后缀表达式(即逆波兰式)
- 中缀表达式转换成后缀表达式以及逆波兰表示法求值
- 关于中缀表达式和逆波兰表达式(终结篇)
- 中缀表达式转换为后缀表达式及逆波兰式计算
- 中缀表达式转化为后缀表达式,计算中缀表达式,计算后缀表达式(有注释)(逆波兰表达式)
- 将中缀表达式转化成后缀表达式(逆波兰式)
- 中缀表达式转后缀表达式(逆波兰表达式)
- 中缀表达式转后缀(逆波兰)表达式
- 逆波兰计算器与中缀表达式向后缀表达式的转化实例
- 关于中缀表达式和逆波兰表达式(终结篇)
- Java实现表达式计算(中缀表达式转化为后缀表达式/逆波兰式)
- 【数据结构】逆波兰表示法(RPN):中缀表达式转后缀表达式
- 逆波兰:将中缀表达式转为后缀表达式
- 关于中缀表达式和逆波兰表达式(终结篇)
- Java实现表达式计算(中缀表达式转化为后缀表达式/逆波兰式)
- Java实现表达式计算(中缀表达式转化为后缀表达式/逆波兰式)
- [置顶] 逆波兰表达式 中缀表达式 后缀表达式
- 逆波兰中 中缀表达式转后缀表达式的方法
- 算法:中缀表达式转换为逆波兰表达式
- 栈应用之将中缀表达式转化为后缀表达式(逆波兰表达式)