由中缀式转换成后缀式,同样使用栈,并运用一些规则来完成。规则介绍如下:
- 当读到的是操作数,立即输出。
- 当读到的是运算符,则先从栈中弹出优先级高于自己的运算符(不包含括号),自己入栈。
- 读到左括号入栈,读到右括号则将栈中元素出栈并输出,直到遇见左括号(括号都不输出)。
- 输入为空后,将栈元素弹出并输出直到栈空。
注意,最后生成的后缀表达式是考虑了运算符优先级的,再配合逆波兰的无优先级概念这一性质,就能够编写出一个带运算符优先级和括号的简易计算器了。
下面是完整的计算器代码,整型四则运算,可加括号。写了一个下午,幸苦呀~
#include <iostream>
#include <vector>
#include <stack>
#include <ctype.h>
#include <cstdlib>
#include <sstream>
using namespace std;
bool IsDigit(string str)
{
for
(int i = 0; i < str.size(); i++)
if
((str.at(i) >
‘9‘
) || (str.at(i) <
‘0‘
))
return
false
;
return
true
;
}
int main()
{
stack<string> s;
vector<string> postfix;
// 存放后缀表达式,作为求运算结果的输入
string input;
while
(cin >> input)
{
if
(IsDigit(input))
//cout << input << ‘ ‘;
postfix.push_back(input);
else
if
(input ==
"("
)
s.push(input);
else
if
(input ==
"+"
|| input ==
"-"
)
{
while
((!s.empty()) && (s.top() !=
"("
))
{
// 弹出优先级大于等于“+”“-”的运算符直到遇到“(”
//cout << s.top() << ‘ ‘;
postfix.push_back(s.top());
s.pop();
}
s.push(input);
}
else
if
(input ==
"*"
|| input ==
"/"
)
{
// 在不知道栈是否为空时,不能top()
while
((!s.empty()) && (s.top() !=
"("
) &&
(s.top() !=
"+"
) && (s.top() !=
"-"
))
{
// 弹出运算符“*”“/”直到遇到“(”
//cout << s.top() << ‘ ‘;
postfix.push_back(s.top());
s.pop();
}
s.push(input);
}
else
if
(input ==
")"
)
{
while
((!s.empty()) && (s.top() !=
"("
))
{
// 弹出直到遇到“(”
//cout << s.top() << ‘ ‘;
postfix.push_back(s.top());
s.pop();
}
s.pop();
// 弹出“(”
}
else
{
// 遇到非法字符
cout <<
"Input illegal"
;
return
-1;
}
}
while
(!s.empty())
{
//cout << s.top() << ‘ ‘;
postfix.push_back(s.top());
s.pop();
}
vector<string>::iterator iter = postfix.begin();
for
( ; iter != postfix.end(); iter++)
cout << *iter;
#if 1
cout << endl;
iter = postfix.begin();
while
(iter != postfix.end())
{
input = *iter;
if
(IsDigit(input))
s.push(input);
else
if
((input ==
"+"
) || (input ==
"-"
) || (input ==
"*"
) || (input ==
"/"
))
{
int lhs = atoi((s.top()).c_str());
s.pop();
int rhs = atoi((s.top()).c_str());
s.pop();
stringstream ss;
string midval;
switch
(*input.c_str())
{
case
‘+‘
:
ss << (lhs+rhs);
ss >> midval;
s.push(midval);
break
;
case
‘-‘
:
ss << (lhs-rhs);
ss >> midval;
s.push(midval);
break
;
case
‘*‘
:
ss << (lhs*rhs);
ss >> midval;
s.push(midval);
break
;
case
‘/‘
:
ss << (rhs/lhs);
// 注意除法的操作数有顺序限制
ss >> midval;
s.push(midval);
break
;
}
}
iter++;
}
cout << s.top();
#endif
return
0;
}
参考:
《数据结构于算法分析》 P54。
栈的应用 — 中缀式转后缀式,码迷,mamicode.com