目录
课前预习:
代码实现过程:
1.先定义一下各运算符的优先级
2.转化成逆波兰式
3.计算逆波兰式
测试结果:
刷题检测网站
1.逆波兰式的定义,如何将中缀表达式转化成逆波兰式
2.为什么要转化成逆波兰式,逆波兰式有什么优点
3.各运算符之间的优先级(+、-、*、/)
4.此计算器只支持输入非负整数数,不支持输入负数,要是非要输入负数可以这样(0-1)
解释:左括号优先级最低,+-略高,*/较高,右括号最高
int priority(string op)
{
if (op == "(") return 0;
if (op == "+" || op == "-") return 1;
else if (op == "*" || op == "/") return 2;
}
几个关键的点
(1)碰到左括号直接进入符号栈
(2)右括号优先级最高,遇到右括号将符号栈中的运算符添加到逆波兰式数组中,直到遇到左括号,并将左括号弹出
(3)当前为运算符,如果栈顶的运算符优先级高于当前或等于(有些文章中将在符号栈中的运算符优先级看做高于栈外同类运算符,我这里不这样了,感觉还是我这样简单点)当前运算符,弹出栈顶运算符添加到逆波兰式数组中(循环)
(4)最后如果符号栈非空,将符号栈中的元素弹出添加到逆波兰式数组中
/*将表达式转换成逆波兰式*/
vector toPolish(string str)
{
stack opstack;
vector polish;
string str1;
for (int i = 0; i < str.size(); i++)
{
if (str[i] == '(') /*左括号*/
{
opstack.push("(");
continue;
}
if (str[i] >= '0'&&str[i] <= '9')/*数字*/
{
str1 = "";
while (i < str.size() && str[i] >= '0'&&str[i] <= '9')
{
str1 += str[i];
i++;
}
i--;
polish.push_back(str1);
continue;
}
if (str[i] == ')')/*右括号*/
{
/*出栈,直到匹配到左括号*/
while (!opstack.empty())
{
if(opstack.top() != "(")
{
polish.push_back(opstack.top());
opstack.pop();
}
else
{
opstack.pop();
break;
}
}
}
else/*加减乘除运算符*/
{
str1 = str[i];
while (!opstack.empty() && priority(opstack.top()) >= priority(str1))
{
polish.push_back(opstack.top());
opstack.pop();
}
opstack.push(str1); // 添加到符号栈中
}
}
//剩余的运算符添加到polish中
while (!opstack.empty())
{
polish.push_back(opstack.top());
opstack.pop();
}
return polish;
}
逆波兰式有个大大的优点,就是符号没有优先级,也就是说我们碰到运算符就进行运算,非常简便
/*将逆波兰式进行计算*/
int calculation(vector polish)
{
stack data;
int a, b, c;
for (int i = 0; i < polish.size(); i++)
{
if (polish[i] == "+" || polish[i] == "-" || polish[i] == "*" || polish[i] == "/")
{
b = data.top(); data.pop();
a = data.top(); data.pop();
if (polish[i] == "+") c = a + b;
else if (polish[i] == "-") c = a - b;
else if (polish[i] == "*") c = a * b;
else if (polish[i] == "/") c = a / b;
data.push(c);
}
else
{
data.push(stoi(polish[i]));/*stoi函数功能:string to int */
}
}
return data.top();
}
以上就是实现过程,下面就是全部代码:
#include
#include
#include
#include
#include
using namespace std;
int priority(string op);
vector toPolish(string str);
int calculation(vector polish);
int main()
{
string str = "1*(1+2*(1*2*2-3+5*1))";
int a = calculation(toPolish(str));
cout << a;
}
/*返回运算符的优先级*/
int priority(string op)
{
if (op == "(") return 0;
if (op == "+" || op == "-") return 1;
else if (op == "*" || op == "/") return 2;
}
/*将表达式转换成逆波兰式*/
vector toPolish(string str)
{
stack opstack;
vector polish;
string str1;
for (int i = 0; i < str.size(); i++)
{
if (str[i] == '(') /*左括号*/
{
opstack.push("(");
continue;
}
if (str[i] >= '0'&&str[i] <= '9')/*数字*/
{
str1 = "";
while (i < str.size() && str[i] >= '0'&&str[i] <= '9')
{
str1 += str[i];
i++;
}
i--;
polish.push_back(str1);
continue;
}
if (str[i] == ')')/*右括号*/
{
/*出栈,直到匹配到左括号*/
while (!opstack.empty())
{
if(opstack.top() != "(")
{
polish.push_back(opstack.top());
opstack.pop();
}
else
{
opstack.pop();
break;
}
}
}
else/*加减乘除运算符*/
{
str1 = str[i];
while (!opstack.empty() && priority(opstack.top()) >= priority(str1))
{
polish.push_back(opstack.top());
opstack.pop();
}
opstack.push(str1); // 添加到符号栈中
}
}
//剩余的运算符添加到polish中
while (!opstack.empty())
{
polish.push_back(opstack.top());
opstack.pop();
}
return polish;
}
/*将逆波兰式进行计算*/
int calculation(vector polish)
{
stack data;
int a, b, c;
for (int i = 0; i < polish.size(); i++)
{
if (polish[i] == "+" || polish[i] == "-" || polish[i] == "*" || polish[i] == "/")
{
b = data.top(); data.pop();
a = data.top(); data.pop();
if (polish[i] == "+") c = a + b;
else if (polish[i] == "-") c = a - b;
else if (polish[i] == "*") c = a * b;
else if (polish[i] == "/") c = a / b;
data.push(c);
}
else
{
data.push(stoi(polish[i]));/*stoi函数功能:string to int */
}
}
return data.top();
}
输入:string str = "1*(1+2*(1*2*2-3+5*1))";
输出:13
如果想要练手,并检验是否正确,可以在Leetcode网站上检测一下
leetcode-计算器
题目和我的代码稍有不同