将一个中缀表达式转化为逆波兰式的一般算法是:
首先分配2个栈,一个作为临时存储运算符的栈sTmp,一个作为输入逆波兰式的栈sPostfit
从中缀式的左端开始取字符,逐序进行如下步骤:
(1)若取出的字符是操作数,则分析出完整的运算数,该操作数直接送入sPostfit栈
(2)若取出的字符是运算符,则将该运算符与sTmp栈栈顶元素比较,
如果该运算符优先级大于sTmp栈栈顶运算符优先级,则将该运算符压入sTmp栈;
否则,将sTmp栈的栈顶运算符弹出,压入sPostfit栈中,
直至sTmp栈栈顶运算符低于(不包括等于)该运算符优先级,则将该运算符压入sTmp栈。
注意优先级关系:”(” < “+”, ”-” < “*”, “/”
(3)若取出的字符是“(”,则直接压入sTmp栈。
(4)若取出的字符是“)”,则将距离sTmp栈栈顶最近的“(”之间的运算符,逐个出栈,依次压入sPostfit栈,此时抛弃“(”。
(5)重复上面的1~4步,直至处理完所有的输入字符
(6)将sTmp栈内所有运算符,逐个出栈,依次压入sPostfit栈。
#include <iostream>
#include <string.h>
#include <stack>
#include <string>
using std::stack;
using std::string;
using std::cout;
using std::cin;
using std::endl;
void ToPostfix(string& exp, string& postfix)
{
stack<char> sTmp;
stack<char> sPostfix;
int len = exp.length();
char cur;
for (int i = 0; i < len; ++i)
{
cur = exp[i];
if ('(' == cur)
sTmp.push(cur);
else if (')' == cur)
{
while ('(' != sTmp.top())
{
sPostfix.push(sTmp.top());
sTmp.pop();
}
sTmp.pop();
}
else if ('+' == cur || '-' == cur)
{
while (!sTmp.empty() && '(' != sTmp.top())
{
sPostfix.push(sTmp.top());
sTmp.pop();
}
sTmp.push(cur);
}
else if ('*' == cur || '/' == cur)
{
while (!sTmp.empty() && ('*' == sTmp.top() || '/' == sTmp.top()))
{
sPostfix.push(sTmp.top());
sTmp.pop();
}
sTmp.push(cur);
}
else
{
sPostfix.push(cur);
}
}
while (!sTmp.empty())
{
sPostfix.push(sTmp.top());
sTmp.pop();
}
int size = sPostfix.size();
char *arr = new char[size+1];
memset(arr, 0, (size+1)*sizeof(char));
for (int j = 0; j < size; ++j)
{
arr[size-j-1] = sPostfix.top();
sPostfix.pop();
}
postfix = arr;
delete []arr;
arr = NULL;
}
测试用例:
(1+5)/3*2-4*2/(1+3)/2-1
15+3/2*42*13+/2/-1-
1*2+(2-1)
12*21-+
8-(3+2*6)/5+4
8326*+5/-4+
(a+b)*c-(a+b)/e
ab+c*ab+e/-
逆波兰式求值:
顺序处理逆波兰式的每一位
如果该位是一个数,将这个数入栈
如果该位是一个运算符,连续进行两次出栈操作,得到两个元素,对这两个元素用该运算符进行运算,将所得的结果压入栈
int CalcPostfix(string& postfix)
{
int len = postfix.length();
char cur;
stack<char> sTmp;
char t1, t2;
int res;
for (int i = 0; i < len; ++i)
{
if (postfix[i] >= '0' && postfix[i] <= '9')
sTmp.push(postfix[i]);
else
{
t1 = sTmp.top();
sTmp.pop();
t2 = sTmp.top();
sTmp.pop();
switch (postfix[i])
{
case '+':
res = (t2 - '0') + (t1 - '0');
break;
case '-':
res = (t2 - '0') - (t1 - '0');
break;
case '*':
res = (t2 - '0') * (t1 - '0');
break;
case '/':
res = (t2 - '0') / (t1 - '0');
break;
}
sTmp.push(res+'0');
}
}
return (sTmp.top() - '0');
}
int main()
{
string expression;
cin >> expression;
string postfix;
ToPostfix(expression, postfix);
cout << "postfix = " << postfix << endl;
int res = CalcPostfix(postfix);
cout << "res = " << res << endl;
return 0;
}
首先分配2个栈,一个作为临时存储运算符的栈sTmp,一个作为输入逆波兰式的栈sPostfit
从中缀式的左端开始取字符,逐序进行如下步骤:
(1)若取出的字符是操作数,则分析出完整的运算数,该操作数直接送入sPostfit栈
(2)若取出的字符是运算符,则将该运算符与sTmp栈栈顶元素比较,
如果该运算符优先级大于sTmp栈栈顶运算符优先级,则将该运算符压入sTmp栈;
否则,将sTmp栈的栈顶运算符弹出,压入sPostfit栈中,
直至sTmp栈栈顶运算符低于(不包括等于)该运算符优先级,则将该运算符压入sTmp栈。
注意优先级关系:”(” < “+”, ”-” < “*”, “/”
(3)若取出的字符是“(”,则直接压入sTmp栈。
(4)若取出的字符是“)”,则将距离sTmp栈栈顶最近的“(”之间的运算符,逐个出栈,依次压入sPostfit栈,此时抛弃“(”。
(5)重复上面的1~4步,直至处理完所有的输入字符
(6)将sTmp栈内所有运算符,逐个出栈,依次压入sPostfit栈。
#include <iostream>
#include <string.h>
#include <stack>
#include <string>
using std::stack;
using std::string;
using std::cout;
using std::cin;
using std::endl;
void ToPostfix(string& exp, string& postfix)
{
stack<char> sTmp;
stack<char> sPostfix;
int len = exp.length();
char cur;
for (int i = 0; i < len; ++i)
{
cur = exp[i];
if ('(' == cur)
sTmp.push(cur);
else if (')' == cur)
{
while ('(' != sTmp.top())
{
sPostfix.push(sTmp.top());
sTmp.pop();
}
sTmp.pop();
}
else if ('+' == cur || '-' == cur)
{
while (!sTmp.empty() && '(' != sTmp.top())
{
sPostfix.push(sTmp.top());
sTmp.pop();
}
sTmp.push(cur);
}
else if ('*' == cur || '/' == cur)
{
while (!sTmp.empty() && ('*' == sTmp.top() || '/' == sTmp.top()))
{
sPostfix.push(sTmp.top());
sTmp.pop();
}
sTmp.push(cur);
}
else
{
sPostfix.push(cur);
}
}
while (!sTmp.empty())
{
sPostfix.push(sTmp.top());
sTmp.pop();
}
int size = sPostfix.size();
char *arr = new char[size+1];
memset(arr, 0, (size+1)*sizeof(char));
for (int j = 0; j < size; ++j)
{
arr[size-j-1] = sPostfix.top();
sPostfix.pop();
}
postfix = arr;
delete []arr;
arr = NULL;
}
测试用例:
(1+5)/3*2-4*2/(1+3)/2-1
15+3/2*42*13+/2/-1-
1*2+(2-1)
12*21-+
8-(3+2*6)/5+4
8326*+5/-4+
(a+b)*c-(a+b)/e
ab+c*ab+e/-
逆波兰式求值:
顺序处理逆波兰式的每一位
如果该位是一个数,将这个数入栈
如果该位是一个运算符,连续进行两次出栈操作,得到两个元素,对这两个元素用该运算符进行运算,将所得的结果压入栈
int CalcPostfix(string& postfix)
{
int len = postfix.length();
char cur;
stack<char> sTmp;
char t1, t2;
int res;
for (int i = 0; i < len; ++i)
{
if (postfix[i] >= '0' && postfix[i] <= '9')
sTmp.push(postfix[i]);
else
{
t1 = sTmp.top();
sTmp.pop();
t2 = sTmp.top();
sTmp.pop();
switch (postfix[i])
{
case '+':
res = (t2 - '0') + (t1 - '0');
break;
case '-':
res = (t2 - '0') - (t1 - '0');
break;
case '*':
res = (t2 - '0') * (t1 - '0');
break;
case '/':
res = (t2 - '0') / (t1 - '0');
break;
}
sTmp.push(res+'0');
}
}
return (sTmp.top() - '0');
}
int main()
{
string expression;
cin >> expression;
string postfix;
ToPostfix(expression, postfix);
cout << "postfix = " << postfix << endl;
int res = CalcPostfix(postfix);
cout << "res = " << res << endl;
return 0;
}