中缀表达式求值代码C++
中缀表达式求值比较合理的做法是:
- 中缀转后缀
- 后缀转二叉树
- 二叉树求值
中缀转后缀
算法
- 0:初始化运算符栈
- 1: 对于数字,直接加入后缀表达式
- 2:对于运算符,与栈顶运算符判断
- 栈顶运算符优先级更高,弹出到后缀表达式,回到2
- 栈顶运算符优先级更低,当前运算符直接压栈
- 3:对于左括号,压栈
- 4:对于右括号,弹出到后缀表达式,直到遇到左括号
- 5:最终结果
流程图
后缀转二叉树
流程图
需要注意的点
- 二叉树节点结构体定义
- 不合法情况的判断,不要忽略括号数量不一致的情况
- 注意对空栈的判断
- 注意正负号问题
- 当前遍历状态的判断
- 中缀表达式中数字结束的判断,其实不需要判断
- 后缀表达式中数字结束的判断,可以用空格判断
- 计算二叉树的值用到递归,注意递归截止条件
- 比较运算符优先级的时候,定义左括号优先级最低,程序就正确了
- 对正号的处理,中缀表达式中的正号在后缀表达式中要去掉
代码
//
// main.cpp
// Expression
//
// Created by Freeverc on 2020/5/11.
// Copyright © 2020 Freeverc. All rights reserved.
//
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
//定义二叉树节点,可以放整数和字符
struct TreeNode {
int val;
char ch;
TreeNode * left, * right;
TreeNode(int num, char c)
{
val = num;
ch = c;
left = nullptr;
right = nullptr;
}
};
// 计算运算符的优先级
bool op_prior(char a, char b)
{
if (a == '(')
return false;
else if(a == '*'|| a =='/' )
return true;
else if(b == '*'|| b =='/' )
return false;
else
return true;
}
//计算二叉树的值
int calcu_btree(TreeNode * root)
{
if(!root)
return 0;
if(!root->left && !root->right)
return root->val;
else{
int leftValue = calcu_btree(root->left);
int rightValue = calcu_btree(root->right);
if(root->ch == '+')
return leftValue + rightValue;
else if(root->ch == '-')
return leftValue - rightValue;
else if(root->ch == '*')
return leftValue * rightValue;
else if(root->ch == '/')
return leftValue / rightValue;
}
return 0;
}
//转化为后追表达式
string to_rpn(string & s)
{
if(s.empty())
return "";
stack<char> op_s;
string rpn= "";
int state = 0;
for(int i = 0;i<s.size();i++)
{
if(s[i] >= '0' && s[i] <= '9')
{
state = 1;
rpn += s[i];
}
else if(s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/')
{
if(s[i] == '-' && state == 0)
{
rpn += s[i];
state = 2;
continue;
}
else if(s[i] == '+' && state == 0)
{
state = 2;
continue;
}
else if(state != 1)
return "";
rpn += ' ';
state = 2;
while(!op_s.empty() && op_prior(op_s.top(), s[i]))
{
rpn += op_s.top();
rpn += ' ';
op_s.pop();
}
op_s.push(s[i]);
}
else if(s[i] == ' ' || s[i] == '\t')
{
continue;
}
else if(s[i] == '(')
{
if(state == 1)
return "";
state = 0;
op_s.push(s[i]);
}
else if(s[i] == ')')
{
if(state != 1)
return "";
rpn += ' ';
while(!op_s.empty() && op_s.top() != '(')
{
rpn += op_s.top();
rpn += ' ';
op_s.pop();
}
if(op_s.empty())
return "";
else
op_s.pop();
}
else{
return "";
}
// cout << i << " : " << rpn <<endl;
}
if(op_s.empty())
return "";
rpn += ' ';
while(!op_s.empty())
{
if(op_s.top() == '(')
return "";
rpn += op_s.top();
rpn += ' ';
op_s.pop();
}
return rpn;
}
//转化为二叉树
TreeNode * to_btree(string & s)
{
if(s.empty())
return nullptr;
stack<TreeNode * > st;
int num = 0;
char ch = 0;
int flag = 1;
int state = 0;
for(int i = 0; i < s.size();i++)
{
if(s[i] == '-' && s[i+1] != ' ')
{
flag = -1;
state = 1;
continue;
}
else if(s[i] >= '0' && s[i] <= '9')
{
state = 1;
num = num * 10 + s[i] - '0';
}
else if(s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/')
{
ch = s[i];
state = 2;
TreeNode * node = new TreeNode(0, ch);
node->right = st.top();
st.pop();
node->left = st.top();
st.pop();
st.push(node);
}
else if(s[i] == ' ')
{
if(state == 1)
{
num *= flag;
TreeNode * leaf = new TreeNode(num, 0);
st.push(leaf);
num = 0;
flag = 1;
state = 0;
}
else
continue;
}
// if(!st.empty())
// cout << calcu_btree(st.top()) << endl;
}
return st.top();
}
int main(int argc, const char * argv[]) {
// insert code here...
// string initStr = "20 + (3 * (4 + 46) - 6)/2-134";
string initStr = "-332 + (+456) * (678 - 789 * (-712 + 987) ) + 64 / 16 * 36 + 20";
cout << "中缀表达式为:" <<initStr << endl;
string rpnStr = to_rpn(initStr);
if(rpnStr.size())
cout << "后缀表达式为:" <<rpnStr << endl;
else
cout << "中缀表达式不合法" << endl;
TreeNode * root = to_btree(rpnStr);
int r = -332 + (+456) * (678 - 789 * (-712 + 987) ) + 64 / 16 * 36 + 20;
cout << "用系统编译器求结果: " << r << endl;
cout << "构造二叉树再求结果: " << calcu_btree(root)<<endl;
return 0;
}