NYOJ-467 中缀式变后缀式【逆波兰法】
2012-03-18 19:02
330 查看
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=467
解题思路:
经典的逆波兰法求表达式的值,以前是用栈模拟的,但是没有仔细研究,现在对表达式求值方法有了一定的了解。
其实表达式求值的通法就是建立一棵表达式树,则,前缀、中缀、后缀表达式分别对应表达式树的前序、中序、后序遍历。
则,通过表达式树就可以对这个问题做一个全面的分析了。另外还有一种方法是基于编译原理的自顶向下分析的方法,还没有研究,等研究好了再重新写吧。
相关知识可以点这里:
逆波兰表示法:http://zh.wikipedia.org/wiki/%E9%80%86%E6%B3%A2%E5%85%B0%E8%A1%A8%E7%A4%BA%E6%B3%95#.E8.A7.A3.E9.87.8A
中缀转后缀法:http://zh.wikipedia.org/wiki/Shunting_yard%E7%AE%97%E6%B3%95
代码如下:
解题思路:
经典的逆波兰法求表达式的值,以前是用栈模拟的,但是没有仔细研究,现在对表达式求值方法有了一定的了解。
其实表达式求值的通法就是建立一棵表达式树,则,前缀、中缀、后缀表达式分别对应表达式树的前序、中序、后序遍历。
则,通过表达式树就可以对这个问题做一个全面的分析了。另外还有一种方法是基于编译原理的自顶向下分析的方法,还没有研究,等研究好了再重新写吧。
相关知识可以点这里:
逆波兰表示法:http://zh.wikipedia.org/wiki/%E9%80%86%E6%B3%A2%E5%85%B0%E8%A1%A8%E7%A4%BA%E6%B3%95#.E8.A7.A3.E9.87.8A
中缀转后缀法:http://zh.wikipedia.org/wiki/Shunting_yard%E7%AE%97%E6%B3%95
代码如下:
/* *表达式求值的经典算法 *编写代码对算术表达式求值的经典方法由 Donald Knuth 描述于 1962 年。 * *Knuth 将此概括为三个步骤: *1、对中缀表达式进行语法分析 *2、中缀表达式到后缀表达式的转换 *3、对后缀表达式求值 * *注意到我们谈到的这个经典算法有些简化:算术表达式只包含操作数、二元操作符和一种括号。 *此外,对于每个操作数和操作符,只用单个字符表示,使语法分析直观。 *表达式表示法: *算术表达式中最常见的表示法形式有 中缀、前缀和 后缀表示法。 *中缀表示法是书写表达式的常见方式,而前缀和后缀表示法主要用于计算机科学领域。 * *中缀表示法: *中缀表示法是算术表达式的常规表示法。称它为中缀表示法是因为每个操作符都位于 *其操作数的中间,这种表示法只适用于操作符恰好对应两个操作数的时候 *(在操作符是二元操作符如加、减、乘、除以及取模的情况下)。 *对以中缀表示法书写的表达式进行语法分析时,需要用括号和优先规则排除多义性。 *Syntax: operand1 operator operand2 *Example: (A+B)*C-D/(E+F) * 前缀表示法 * 前缀表示法中,操作符写在操作数的前面。这种表示法经常用于计算机科学, * 特别是编译器设计方面。为纪念其发明家 ― Jan Lukasiewicz, * 这种表示法也称 波兰表示法。 *Syntax : operator operand1 operand2 *Example : -*+ABC/D+EF * *后缀表示法 * 在后缀表示法中,操作符位于操作数后面。后缀表示法也称 逆波兰表示法 * (reverse Polish notation,RPN),因其使表达式求值变得轻松,所以被普遍使用。 *Syntax : operand1 operand2 operator *Example : AB+C*DEF+/- *前缀和后缀表示法有三项公共特征: *操作数的顺序与等价的中缀表达式中操作数的顺序一致 *不需要括号 *操作符的优先级不相关 * *中缀转化为后缀算法: *a.得到一操作符或操作数; *b.若输入为操作数,则输出到数组,转a; *c. 若输入为'(',压栈,转a; *d.若输入为')',栈顶出栈,输出到数组,直至栈顶为'(',抛弃'(', 转a; *e.若输入为操作符, * 若栈空或栈顶为'('或操作符.忧先级大于栈顶操作符,压栈,转a * 若操作符优先级小于栈顶操作符,则出栈,输出至数组,转e; *d.若输入结束,出栈,输出到数组,直至栈空。 *数组SNode中即为后缀表达式; * *优先级可以根据需要分为:栈内优先级和栈外优先级 * *后缀表达式求值 *对后缀表达式求值比直接对中缀表达式求值简单。在后缀表达式中,不需要括号, *而且操作符的优先级也不再起作用了。您可以用如下算法对后缀表达式求值:初始化一个空堆栈 *从左到右读入后缀表达式,如果字符是一个操作数,把它压入堆栈。如果字符是个操作符, *弹出两个操作数,执行恰当操作,然后把结果压入堆栈。如果您不能够弹出两个操作数, *后缀表达式的语法就不正确。到后缀表达式末尾,从堆栈中弹出结果。 *若后缀表达式格式正确,那么堆栈应该为空。 */ #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<climits> #include<vector> #include<stdlib.h> #include<algorithm> using namespace std; const int N = 1010; char str ; vector<double> num; //操作数 vector<char>ope; //运算符 int judge_oper(const char ch) //运算符优先级 { switch(ch) { case '=' : return 1; case '+' : return 2; case '-' : return 2; case '*' : return 3; case '/' : return 3; case '(' : return 0; case ')' : return 0; }; } int main() { int ncase; scanf("%d", &ncase); int len; //字符串长度 double temp; //字符串中提取操作数 int length; //操作数位数 while(ncase--) { memset(str, '\0', sizeof(str)); num.clear(); ope.clear(); ope.push_back('='); getchar(); scanf("%s", str); len = strlen(str) - 1; for(int i = 0; i < len; ++i) { if(str[i] >= '0' && str[i] <= '9') //操作数 { sscanf(&str[i], "%lf%n", &temp, &length); num.push_back(temp); for(int j = i; j < i + length; ++j) printf("%c", str[j]); printf(" "); i += length - 1; } else //运算符 { if(str[i] == '(' || judge_oper(str[i]) > judge_oper(ope.back())) ope.push_back(str[i]); else { if(str[i] == ')') { while(ope.back() != '(') { printf("%c ", ope.back()); ope.pop_back(); } ope.pop_back(); } else { while( judge_oper(str[i]) <= judge_oper( ope.back() ) && ope.back() != '(') { printf("%c ", ope.back()); ope.pop_back(); } ope.push_back(str[i]); } } } } while(!ope.empty()) { printf("%c ", ope.back()); ope.pop_back(); } printf("\n"); } return 0; }
相关文章推荐
- NYOJ467 中缀式变后缀式 【栈】
- NYOJ467 中缀式转后缀式 java
- NYOJ 467 中缀式变后缀式【栈】
- NYOJ-35-表达式求值(中缀式转后缀式 逆波兰表达式)
- 中缀式变后缀式(nyoj 467)
- nyoj 467 中缀式变后缀式 nyoj 257 郁闷的C小加(一)
- 第九届河南省程序设计大赛-NYOJ-1272-表达式求值(中缀式转后缀式 逆波兰表达式)
- 如何将中缀式转化成前缀式和后缀式(波兰和逆波兰)(适合考试使用的简单办法)
- nyoj-409 郁闷的C小加(三) (表达式求值,中缀式转前缀式,中缀式转后缀式)
- 如何将中缀式转化成前缀式和后缀式(波兰和逆波兰)结合二叉树(适合数据结构方面的理解)
- 中缀式转换为后缀式(逆波兰式)方法
- nyoj 467 中缀事变后缀式
- 中缀式转换为后缀式(逆波兰式)方法
- nyoj 1272 表达式求值(中缀式转后缀式)
- 算法题:四则运算(中缀式到后缀式的转换,值得思考的逆波兰式)
- 前缀式(波兰式)与后缀式(逆波兰式)求解表达式的值,中缀式(一般算数表达式不做讨论)
- 中缀式转换为后缀式(逆波兰式)方法
- 中缀式转换为后缀式(逆波兰式)方法
- NYOJ 467 中缀式变后缀式
- NYOJ 467 中缀式变后缀式(栈)