#include<iostream>
#include<string>
#include<cctype>//这个是isdigit的头文件
#include<stack>//这代码其实就看你怎么理解 也可以理解为栈 也可以理解为二叉树
#include<unordered_map>//这个地方应该使用map因为这个map是一个既有key又有value
using namespace std;
//stack<pair<string, int>>z; 这个地方真的就不能用这个东西否则没法比较优先级 这个没法比较优先级
stack<int>u;
unordered_map<char, int>z = { {'+',1} ,{'-',1} ,{'*',2} ,{'/',2}};//利用哈希表定义级别便于后续运算
stack<char>v;
void jisuan()
{
int num1 = u.top();
u.pop();
int num2 = u.top();
u.pop();
char c = v.top();
v.pop();
if (c == '+')
{
u.push(num1 + num2);
}
if (c == '-')
{
u.push(num2 - num1);
}
if (c == '*')
{
u.push(num1 * num2);
}
if (c == '/')
{
u.push(num2 / num1);
}
}
int main()
{
string s;
cin >> s;
for (int i = 0; i < s.size(); i++)
{
if (isdigit(s[i]))//先处理数字 然后在处理括号 再处理这个运算符
{
int x = 0, j = i;
while (j < s.size() && isdigit(s[j]))x = 10 * x + s[j++] - '0';
i = j - 1;
u.push(x);
}
else if(s[i]=='(')
{
v.push(s[i]);
}
else if (s[i] == ')')
{
while (v.size() && v.top() != '(')jisuan();
v.pop();
}
else
{while(v.size() && z[v.top()] >= z[s[i]])//这个地方就相当于是如果发现这个v里面的优先级更高就先算v里面的
jisuan();
v.push(s[i]);//算完之后再把这个字符放进去
}
}
while (v.size())
{
jisuan();
}
cout << u.top();
}
#### 栈表达式求值 中缀
以下这些代码有借鉴力扣上面的
```
对于这种入栈出栈问题我们可以把他理解为就是那种递归,想象一下,先进入栈中然后从栈中出来一个数,就是你也一这么想,对于一下的代码,你可以理解为
1.先利用一个哈希表
2.在脑海里面可以先想起来那个那个二叉树就是你可以想树杈就是先从下面开始,就是先把数值先算好,在往上整,如果说上面的优先级高就先算上面的,然后在从下在开始往上面计算,然后
3.发现要是有括号的在应该先找到括号右边的这样在从右向左计算
4.最后因为发现没有括号了,在利用像递归一样的思想相当于在从右边开始计算
补充(这种想法可以叫做后缀遍历法)
5.其实仔细想一下这个代码是不就相当于是先把每一小块计算好后,在同一计算
中缀表达式和后缀表达式是两种不同的表达方式,它们之间并不直接相连。在计算机科学中,后缀表达式也称为逆波兰表达式,它不需要括号来表示运算符的优先级,而中缀表达式则需要使用括号来明确优先级。
虽然后缀表达式在计算机中更容易求解,但中缀表达式仍然具有它的用途和优点:
1. **可读性高**:人们更习惯于阅读和书写中缀表达式,因为它们更接近我们常见的数学表达方式。
2. **易于输入**:中缀表达式更容易由人类输入,因为它们无需考虑运算符的优先级。
3. **便于编辑**:中缀表达式可以很容易地通过添加或删除括号来调整运算符的优先级,这样可以更灵活地表示计算意图。
4.
以下这个代码就可以叫做中缀表达式中利用后缀
```c++
#include <iostream>
#include <string>
#include <stack>
#include <unordered_map>
using namespace std;
stack<char> op;
stack<int> num;
unordered_map<char, int> pr = {{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}};
void eval()
{
int b = num.top(); num.pop();
int a = num.top(); num.pop();
char c = op.top(); op.pop();
int x;
if(c == '+') x = a + b;
else if(c == '-') x = a - b;
else if(c == '*') x = a * b;
else x = a / b;
num.push(x);
}
int main()
{
string s;
cin >> s;
for(int i = 0; i < s.size(); i++)
{
char c = s[i];
if(isdigit(c))
{
int x = 0, j = i;
while(j < s.size() && isdigit(s[j])) x = 10 * x + s[j++] - '0';
i = j - 1;
num.push(x);
}
else if(c == '(') op.push(c);
else if(c == ')')
{
while(op.size() && op.top() != '(') eval();
op.pop();
}
else
{ while(op.size() && pr[op.top()] >= pr[c]) eval(); op.push(c);
}
}
while(op.size()) eval();
cout << num.top() << endl;
return 0;
}
```
##### 逆波兰 后缀
```c++
class Solution {
public:
int evalRPN(vector<string>& tokens) {
// 力扣修改了后台测试数据,需要用longlong
stack<long long> st;
for (int i = 0; i < tokens.size(); i++) {
if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {
long long num1 = st.top();
st.pop();
long long num2 = st.top();
st.pop();
if (tokens[i] == "+") st.push(num2 + num1);
if (tokens[i] == "-") st.push(num2 - num1);
if (tokens[i] == "*") st.push(num2 * num1);
if (tokens[i] == "/") st.push(num2 / num1);
} else {
st.push(stoll(tokens[i]));
}
}
int result = st.top();
st.pop(); // 把栈里最后一个元素弹出(其实不弹出也没事)
return result;
}
};
后续补充
#include<iostream>
#include<string>
using namespace std;
#include<stack>
int main()
{
stack<int>u;
string s;
cin >> s;
for (int i = 0; i < s.size();i++)
{
char s1 = s[i];
if (s1=='+'|| s1 == '-'||s1== '*'||s1 == '/')
{
int num1 = u.top();
u.pop();
int num2 = u.top();
u.pop();
/*char s2 = u.top();
u.pop() 这个地方根本就没有必要写 因为在这里面相当于 这个栈里面只有数字没有运算符 ;*/
if (s1 == '+')
{
u.push(num1 + num2);
}
if (s1 == '-')
{
u.push(num2 - num1);
}
if (s1 == '*')
{
u.push(num2 * num1);
}
if (s1 == '/')
{
u.push(num2 / num1);
}
}
else
{
u.push(s[i]-'0');
}
}
int result = u.top();
u.pop();//但是这个代码存在的缺点就是只能实现这个个位的运算不能实现十位····
cout << result;
}
```
#include<iostream>
#include<string>
#include<cctype>//这个是isdigit的头文件
#include<stack>//这代码其实就看你怎么理解 也可以理解为栈 也可以理解为二叉树
#include<unordered_map>//这个地方应该使用map因为这个map是一个既有key又有value
using namespace std;
//stack<pair<string, int>>z; 这个地方真的就不能用这个东西否则没法比较优先级 这个没法比较优先级
stack<int>u;
unordered_map<char, int>z = { {'+',1} ,{'-',1} ,{'*',2} ,{'/',2}};//利用哈希表定义级别便于后续运算
stack<char>v;
void jisuan()
{
int num1 = u.top();
u.pop();
int num2 = u.top();
u.pop();
char c = v.top();
v.pop();
if (c == '+')
{
u.push(num1 + num2);
}
if (c == '-')
{
u.push(num2 - num1);
}
if (c == '*')
{
u.push(num1 * num2);
}
if (c == '/')
{
u.push(num2 / num1);
}
}
int main()
{
string s;
cin >> s;
for (int i = 0; i < s.size(); i++)
{
if (isdigit(s[i]))//先处理数字 然后在处理括号 再处理这个运算符
{
int x = 0, j = i;
while (j < s.size() && isdigit(s[j]))x = 10 * x + s[j++] - '0';
i = j - 1;
u.push(x);
}
else if(s[i]=='(')
{
v.push(s[i]);
}
else if (s[i] == ')')
{
while (v.size() && v.top() != '(')jisuan();
v.pop();
}
else
{while(v.size() && z[v.top()] >= z[s[i]])//这个地方就相当于是如果发现这个v里面的优先级更高就先算v里面的
jisuan();
v.push(s[i]);//算完之后再把这个字符放进去
}
}
while (v.size())
{
jisuan();
}
cout << u.top();
}