2015年7月12日。
什么是中缀表达式呢?中缀表达式(或中缀记法)是一个通用的算术或逻辑公式表示方法, 运算符是以中缀形式处于运算数的中间,中缀表达式是人们常用的算术表示方法。简单地说就是平常做的数学题:给你一个式子将值求出来。比如
1+2∗(4−3)
,答案就是3。对于人们来说这种事情就是小儿科了吧,很方便就求出了,但是在计算机的世界,计算机并不认识这种表达式,也做不出来这种数学题,所以说计算机还是挺”笨”的嘛。
平常所看到的几乎是中缀表达式,人们能够方便运算,而在计算机世界需要将中缀表达式转换成后缀表达式来处理,并不是说一定要转化成后缀表达式才能做,其他方法也可以做,只是说转换成后缀表达式计算机能比较方便与简单地处理。
再来看看后缀表达式是什么,即不包含括号,运算符放在两个运算数的后面,所有的计算按运算符出现的顺序,严格从左向右进行,不再考虑运算符的优先规则。
中缀表达式中可能有括号,括号会影响运算顺序,后缀表达式则只包含云算数和运算符,没有括号影响运算顺序,直接从左往右依次求值即可。
一个字符串(此时是中缀表达式),如何才能转换成后缀表达式方便计算呢?
首先设立一个栈,存储运算符,从左往右处理
1.若遇运算数,则处理连续的运算数,并输出到后缀表达式
2.若栈空,则将运算符压栈
3.若遇’(‘运算符,则将运算符压栈
4.若遇’)’运算符,则出栈直到’(‘,并将出栈的运算符输出至后缀表达式
5.遇到其他运算符:加减乘除,则弹出所有优先级大于或者等于该运算符的栈顶元素并将出栈的运算符输出至后缀表达式,然后将该运算符入栈
6.将栈中所有元素输出至后缀表达式
注:将中缀表达式转化成后缀表达式时,运算符与运算数加上空格以示区分。
如何求出后缀表达式的真实的值呢?
设立一个栈,存储运算数,从左往右处理
1.若遇运算数,则将后缀表达式连续的运算转换为一个运算数,并压栈
2.否则在栈中取出两个运算数,做运算,并将结果压栈
3.处理完后缀表达式后,最后栈中只剩一个运算数,即值
代码如下,仅供参考:
/*
Author: Royecode
Email: Royecode@163.com
Date: 2015/07/12
*/
#include <iostream>
#include <string>
#include <map>
#include <stack>
using namespace std;
int solve()
{
//假设运算数只是数字,数字可以是多位数,运算符只有+ - * / ( ),其他情况雷同
map <char, int> Map; //定义运算符的优先级
Map['('] = 0;
Map['+'] = Map['-'] = 1;
Map['*'] = Map['/'] = 2;
string st1;
cin >> st1;
int len1 = st1.length();
stack <char> Stack1; //存储中缀表达式的运算符
string st2; //存储后缀表达式
//将中缀表达式转换为后缀表达式
for(int i = 0; i < len1; ++i)
{
if(st1[i] == ' ') continue;
if(st1[i] >= '0' && st1[i] <= '9') //1.处理连续的数字,并输出到后缀表达式
{
int j = i;
while(j < len1 && st1[j] >= '0' && st1[j] <= '9')
{
st2 += st1[j];
j++;
}
st2 += ' ';
i = j - 1;
}
else if(Stack1.empty()) Stack1.push(st1[i]); //2.若栈空,将运算符压栈
else if(st1[i] == '(') Stack1.push(st1[i]); //3.若遇'('运算符,压栈
else if(st1[i] == ')') //4.若遇')'运算符,出栈直到'(',并将出栈的运算符输出至后缀表达式
{
while(Stack1.top() != '(')
{
st2 += Stack1.top();
st2 += ' ';
Stack1.pop();
}
Stack1.pop();
}
else //5.遇到其他运算符:加减乘除,弹出所有优先级大于或者等于该运算符的栈顶元素并将出栈的运算符输出至后缀表达式,然后将该运算符入栈
{
while(!Stack1.empty() && Map[Stack1.top()] >= Map[st1[i]])
{
st2 += Stack1.top();
st2 += ' ';
Stack1.pop();
}
Stack1.push(st1[i]);
}
}
while(!Stack1.empty()) //6.将栈中所有元素输出至后缀表达式
{
if(Stack1.top() != '(' && Stack1.top() != ')')
{
st2 += Stack1.top();
st2 += ' ';
}
Stack1.pop();
}
int len2 = st2.length();
stack <int> Stack2; //存储运算数
//运算后缀表达式
for(int i = 0; i < len2; i += 2)
{
if(st2[i] >= '0' && st2[i] <= '9') //1.将后缀表达式连续的数字转换为一个数字,并压栈
{
int j = i, v = 0;
while(j < len2 && st2[j] >= '0' && st2[j] <= '9')
{
v = v * 10 + st2[j] - '0';
j++;
}
i = j - 1;
Stack2.push(v);
}
else //2.取出两个运算数,做运算,并将结果压栈
{
int a = Stack2.top(); Stack2.pop();
int b = Stack2.top(); Stack2.pop();
int c;
if(st2[i] == '+') c = b + a;
else if(st2[i] == '-') c = b - a;
else if(st2[i] == '*') c = b * a;
else c = b / a;
Stack2.push(c);
}
}
return Stack2.top();
}
int main()
{
int val = solve();
cout << val;
return 0;
}
/*
input:
(1+2)*((8-2)/(7-4))
output:
6
*/
再来看看中缀表达式转后缀表达式有什么实际应用呢。
应用1:算出中缀表达式的值,做法:将中缀表达式转化成后缀表达式并求出其值。比如Leetcode Basic Calculator II
应用2:判断两个中缀表达式是否相等,做法:将两中缀表达式分别转换成后缀表达式直接比较即可
应用……
转载请注明出处:http://blog.csdn.net/Royecode/article/details/46850133