一、引入
在程序中实现四则运算,我们不仅需要考虑加减乘除的顺序,还需要考虑括号的问题,这使得我们的程序非常麻烦,但基于栈这种数据结构,我们可以很方便的进行操作。
例如:中缀表达式 9+(3-1)*3+10/2,我们可以把它化为后缀表达式(也叫逆波兰表达式) 9 3 1 - 3 * + 10 2 / + 对于这样一串表达式,我们可以用栈来对它进行操作。
二、运用
基本思想是:
对于每一个元素,如果是数字,则入栈,如果是符号,则将栈顶的两个元素取出进行运算,再将运算结果入栈。
运算过程:
1、先将 9 3 1 入栈,下一个元素是减号,则将3 和1 取出,进行3 - 1 = 2 ,再将2入栈
2、将3 入栈后,下一个元素是乘号,则进行2 * 3 = 6 ,再将6入栈
3、进行9 + 6 = 15 然后入栈,10 、2 入栈后进行10 / 2 = 5 入栈,再进行15 + 5 = 20
最终得出答案等于20;
中缀表达式转换为后缀表达式
从左到右依次遍历中缀表达式,如果是数字则输出,如果是符号,则判断当前符号与此时栈顶的符号的优先级,若当前符号优先级高于栈顶,则入栈,否则将栈内符号全部出栈,将当前符号入栈;
过程
接下来引用《大话数据结构》里的图片:
四、代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<algorithm>
#include<cmath>
#include<stack>
using namespace std;
typedef long long ll;
stack <char> st1;
stack <int> st2;
int fun(char c) //判断符号的优先级
{
if (c == '+' || c == '-')
return 1;
else if (c == '*' || c == '/')
return 2;
else
return 3;
}
void js(char c) //将栈顶两个数拿出来计算,并将结果压入栈中
{
int b = st2.top();
st2.pop();
int a = st2.top();
st2.pop();
int tmp = 0;
if (c == '+')
tmp = a + b;
else if (c == '-')
tmp = a - b;
else if (c == '*')
tmp = a * b;
else
tmp = a / b;
st2.push(tmp);
}
int main()
{
string a;
getline(cin, a); //以字符串的形式输入
int l = a.length();
for (int i = 0; i < l; i++)
{
if (a[i] >= '0' && a[i] <= '9')
{
int tmp = 0;
while (a[i] >= '0' && a[i] <= '9')
{
tmp = tmp * 10 + a[i] - '0';
if (a[i + 1] >= '0' && a[i + 1] <= '9')
i++;
else break;
}
st2.push(tmp); //可以读入多位数字
}
else
{
if (st1.empty())
st1.push(a[i]);
else
{
if (fun(a[i]) >= fun(st1.top())||fun(st1.top())==3)
{
st1.push(a[i]);
if (a[i] == ')') // 遇到括号则将左括号之前的符号全部输出进行运算
{
st1.pop();
while (st1.top() != '(')
{
js(st1.top());
st1.pop();
}
st1.pop();
}
}
else
{
while (!st1.empty()) //如果当前符号优先级比栈顶的优先级小,则将栈中所有符号进行运算并将当前符号压入栈中
{
js(st1.top());
st1.pop();
}
st1.push(a[i]);
}
}
}
}
while (!st1.empty()) // 将剩余符号进行运算
{
js(st1.top());
st1.pop();
}
cout << st2.top();
return 0;
}
//9+(3-1)*3+10/2