NYOJ_467 中缀式变后缀式
2016-07-09 18:36
260 查看
描述 人们的日常习惯是把算术表达式写成中缀式,但对于机器来说更“习惯于”后缀式,关于算术表达式的中缀式和后缀式的论述一般的数据结构书都有相关内容可供参看,这里不再赘述,现在你的任务是将中缀式变为后缀式。
输入第一行输入一个整数n,共有n组测试数据(n<10)。
每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式的中缀式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数。
数据保证除数不会为0输出每组都输出该组中缀式相应的后缀式,要求相邻的操作数操作符用空格隔开。样例输入
样例输出
分析:
我们把平时所用的标准四则运算表达式,即“9+(3-1)*3+10/2"叫做中缀表达式。因为所有的运算符号都在两数字的中间,现在我们的问题就是中缀到后缀的转化。
中缀表达式“9+(3-1)*3+10/2”转化为后缀表达式“9 3 1-3*+ 10 2/+”
规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于或等于栈顶符号(乘除优先加减)则栈顶元素依次出找并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。
下面我们来具体看看这个过程。
1. 初始化一空栈,用来对符号进出栈使用。
2. 第一个字符是数字9,输出9,后面是符号“+”,进栈。
3. 第三个字符是“(”,依然是符号,因其只是左括号,还未配对,故进栈。
4. 第四个字符是数字3,输出,总表达式为9 3,接着是“-”进栈。
5. 接下来是数字1,输出,总表达式为9 3 1,后面是符号“)”,此时,我们需要去匹配此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”,因此输出“-”,总的输出表达式为9 3 1 -
6. 接着是数字3,输出,总的表达式为9 3 1 - 3 。紧接着是符号“*”,因为此时的栈顶符号为“+”号,优先级低于“*”,因此不输出,进栈。
7. 之后是符号“+”,此时当前栈顶元素比这个“+”的优先级高,因此栈中元素出栈并输出(没有比“+”号更低的优先级,所以全部出栈),总输出表达式为 9 3 1 - 3 * +.然后将当前这个符号“+”进栈。也就是说,前6张图的栈底的“+”是指中缀表达式中开头的9后面那个“+”,而下图中的栈底(也是栈顶)的“+”是指“9+(3-1)*3+”中的最后一个“+”。
8. 紧接着数字10,输出,总表达式变为9 3 1-3 * + 10。
9. 最后一个数字2,输出,总的表达式为 9 3 1-3*+ 10 2
10. 因已经到最后,所以将栈中符号全部出栈并输出。最终输出的后缀表达式结果为 9 3 1-3*+ 10 2/+
从刚才的推导中你会发现,要想让计算机具有处理我们通常的标准(中缀)表达式的能力,最重要的就是两步:
将中缀表达式转化为后缀表达式(栈用来进出运算的符号)。
将后缀表达式进行运算得出结果(栈用来进出运算的数字)。
整个过程,都充分利用了找的后进先出特性来处理,理解好它其实也就理解好了栈这个数据结构。
代码:
#include<cstdlib>
#include<string.h>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<ctime>
#include<cstdio>
#include<stack>
#include<map>
#include<queue>
#include<vector>
#include<cctype>
using namespace std;
char ss[30000];
int cmp(char c)
{
switch(c)
{
case '+':
case '-': return 1;
case '*':
case '/': return 2;
default : return -1;
}
}
void fun()
{
int len = strlen(ss);
stack<char> sta;
for(int i=0;i<len;)
{
if(isdigit(ss[i]))
{
string res;
while( i<len && (isdigit(ss[i]) || ss[i]=='.') )
{
res+=ss[i++];
}
cout<<res<<' ';
}
else if(ss[i]=='=')
{
i++;
}
else
{
if(ss[i]==')') //碰到一个右括号,直接弹到与它匹配的左括号结束
{
while(sta.top()!='(')
{
char temp = sta.top();
cout<<temp<<' ';
sta.pop();
}
sta.pop(); //将左括号从栈中弹出
i++;
}
else if(ss[i]=='(')
{
sta.push(ss[i]);
i++;
}
else if(sta.empty() || cmp(ss[i]) > cmp(sta.top()) )
{
sta.push(ss[i]);
i++;
}
else
{
while(!sta.empty() && cmp( sta.top() ) >= cmp(ss[i]) )
{
char temp = sta.top();
sta.pop();
cout<<temp<<' ';
}
sta.push(ss[i]);
i++;
}
}
}
while(!sta.empty()) //将剩余的符号全部弹出栈
{
char temp = sta.top();
sta.pop();
cout<<temp<<' ';
}
}
int main()
{
int tt;
scanf("%d",&tt);
while(tt--)
{
scanf("%s",ss);
fun();
cout<<'='<<endl;
}
return 0;
}
输入第一行输入一个整数n,共有n组测试数据(n<10)。
每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式的中缀式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数。
数据保证除数不会为0输出每组都输出该组中缀式相应的后缀式,要求相邻的操作数操作符用空格隔开。样例输入
2 1.000+2/4= ((1+2)*5+1)/4=
样例输出
1.000 2 4 / + = 1 2 + 5 * 1 + 4 / =
分析:
我们把平时所用的标准四则运算表达式,即“9+(3-1)*3+10/2"叫做中缀表达式。因为所有的运算符号都在两数字的中间,现在我们的问题就是中缀到后缀的转化。
中缀表达式“9+(3-1)*3+10/2”转化为后缀表达式“9 3 1-3*+ 10 2/+”
规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于或等于栈顶符号(乘除优先加减)则栈顶元素依次出找并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。
下面我们来具体看看这个过程。
1. 初始化一空栈,用来对符号进出栈使用。
2. 第一个字符是数字9,输出9,后面是符号“+”,进栈。
3. 第三个字符是“(”,依然是符号,因其只是左括号,还未配对,故进栈。
4. 第四个字符是数字3,输出,总表达式为9 3,接着是“-”进栈。
5. 接下来是数字1,输出,总表达式为9 3 1,后面是符号“)”,此时,我们需要去匹配此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”,因此输出“-”,总的输出表达式为9 3 1 -
6. 接着是数字3,输出,总的表达式为9 3 1 - 3 。紧接着是符号“*”,因为此时的栈顶符号为“+”号,优先级低于“*”,因此不输出,进栈。
7. 之后是符号“+”,此时当前栈顶元素比这个“+”的优先级高,因此栈中元素出栈并输出(没有比“+”号更低的优先级,所以全部出栈),总输出表达式为 9 3 1 - 3 * +.然后将当前这个符号“+”进栈。也就是说,前6张图的栈底的“+”是指中缀表达式中开头的9后面那个“+”,而下图中的栈底(也是栈顶)的“+”是指“9+(3-1)*3+”中的最后一个“+”。
8. 紧接着数字10,输出,总表达式变为9 3 1-3 * + 10。
9. 最后一个数字2,输出,总的表达式为 9 3 1-3*+ 10 2
10. 因已经到最后,所以将栈中符号全部出栈并输出。最终输出的后缀表达式结果为 9 3 1-3*+ 10 2/+
从刚才的推导中你会发现,要想让计算机具有处理我们通常的标准(中缀)表达式的能力,最重要的就是两步:
将中缀表达式转化为后缀表达式(栈用来进出运算的符号)。
将后缀表达式进行运算得出结果(栈用来进出运算的数字)。
整个过程,都充分利用了找的后进先出特性来处理,理解好它其实也就理解好了栈这个数据结构。
代码:
#include<cstdlib>
#include<string.h>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<ctime>
#include<cstdio>
#include<stack>
#include<map>
#include<queue>
#include<vector>
#include<cctype>
using namespace std;
char ss[30000];
int cmp(char c)
{
switch(c)
{
case '+':
case '-': return 1;
case '*':
case '/': return 2;
default : return -1;
}
}
void fun()
{
int len = strlen(ss);
stack<char> sta;
for(int i=0;i<len;)
{
if(isdigit(ss[i]))
{
string res;
while( i<len && (isdigit(ss[i]) || ss[i]=='.') )
{
res+=ss[i++];
}
cout<<res<<' ';
}
else if(ss[i]=='=')
{
i++;
}
else
{
if(ss[i]==')') //碰到一个右括号,直接弹到与它匹配的左括号结束
{
while(sta.top()!='(')
{
char temp = sta.top();
cout<<temp<<' ';
sta.pop();
}
sta.pop(); //将左括号从栈中弹出
i++;
}
else if(ss[i]=='(')
{
sta.push(ss[i]);
i++;
}
else if(sta.empty() || cmp(ss[i]) > cmp(sta.top()) )
{
sta.push(ss[i]);
i++;
}
else
{
while(!sta.empty() && cmp( sta.top() ) >= cmp(ss[i]) )
{
char temp = sta.top();
sta.pop();
cout<<temp<<' ';
}
sta.push(ss[i]);
i++;
}
}
}
while(!sta.empty()) //将剩余的符号全部弹出栈
{
char temp = sta.top();
sta.pop();
cout<<temp<<' ';
}
}
int main()
{
int tt;
scanf("%d",&tt);
while(tt--)
{
scanf("%s",ss);
fun();
cout<<'='<<endl;
}
return 0;
}
相关文章推荐
- hdu-4821-String-HASH
- 51NOD 1276 岛屿的数量(脑洞 + 思维)
- 哪些英语母语者常用的词组对于普通中国大学生来说是生疏的?
- POJ1417 True Liars (并查集+背包)
- 6. 模块
- leetcode题解日练--2016.7.9
- JSP内置对象及其应用场合
- Gradle详解+Groovy
- 将数据库中表的数据保存到XML文件中
- find命令详解
- jQuery事件冒泡机制与解决
- The Tower of Babylon
- WebService学习总结八 WebService 拦截器
- 括号匹配
- LeetCode - 63. Unique Paths II
- Sublime text3插件Emment安装好但不能使用的解决办法
- mybatis分页的三种方案
- 使用HTML5 Notification实现桌面通知
- 面向对象知识点总结
- android studio gradle 配置模板