中缀表达式转后缀表达式
栈实现
1.从左到右扫描字符串
2.如果遇到数字,就输出
3.如果遇到运算符,
(1)栈空时,直接入栈
(2)栈非空时,与栈顶元素进行优先级比较,如果运算符优先级大,入栈,
反之,则弹出优先级小的栈顶元素(并输出)直到运算符符合入栈条件,入栈
int Judge(char ch){
if(ch == '+') return 1;
if(ch == '-') return 1;
if(ch == '*') return 2;
if(ch == '/') return 2;
if(ch == '(') return 0;
if(ch == ')') return 0;
}
string trans(string str){
string s;
stack<char> mid;//存放运算符
int i = 0;
while(str[i] != '='){
if(str[i] == '('){ //判断,左括号进栈
mid.push(str[i]);
i++;
}else if(str[i] == ')'){ //遇右括号则将左括号及左括号以上标识符出栈
while(mid.top() != '('){
s = s + mid.top();
s += ' ';
mid.pop();
}
mid.pop();//左括号出栈
i++;
}else if(isdigit(str[i])){//数字或小数点则直接转入后缀表达式
while(str[i] <= '9' && str[i] >= '0' || str[i] == '.'){
s = s + str[i];
i++;
}
s += ' ';
}else if(str[i] == '+' ||str[i] == '-' ||str[i] == '*' ||str[i] == '/' ){
while(!mid.empty() && Judge(mid.top()) >= Judge(str[i])){
//当运算符优先级低于栈顶元素,出栈操作
s = s + mid.top();
s = s + ' ';
mid.pop();
}
mid.push(str[i]);//当前运算符进栈
i++;
}
}
while(!mid.empty()){//将最后剩余运算符出栈
s = s + mid.top();
s = s + ' ';
mid.pop();
}
return s;
}
括号法
1.首先按照优先级给表达式加上括号:((a+(b*c))+((((d*e)+f)*g))
2.把运算符号移动到对应的括号后面:((a(bc)*)+((((de)*f)+g)*)+
3.去掉括号:abc*+de*f+g*+
后缀表达式求值
void Evaluate(string s){ //s:逆波兰式(后缀表达式)
string temp;
stringstream ss(s);
stack<double> ans;
char a[1000];
double num;
int i;
while(ss >> temp){
//将数字字符串转化为数字
if(isdigit(temp[0])){
for( i = 0; i < temp.length(); i++){
a[i] = temp[i];
}
a[i] = '\0';
num = atof(a); //atof()不支持string型,支持char型
ans.push(num); //数字进栈
}else{ //运算符操作
double x, y;
x = ans.top(); ans.pop();
y = ans.top(); ans.pop();
if(temp == "+") num = x + y;
if(temp == "-") num = y - x;
if(temp == "*") num = x * y;
if(temp == "/") num = y / x;
ans.push(num);
}
}
printf("%.2lf\n", ans.top());
//printf("%d\n", (int)ans.top());
}
逆波兰算法模板
/**
样例输入
2
1.000+2/4=
((1+2)*5+1)/4=
样例输出
1.50
4.00
*/
#include <bits/stdc++.h>
using namespace std;
int Judge(char ch){
//运算符进行优先级划分
if(ch == '+') return 1;
if(ch == '-') return 1;
if(ch == '*') return 2;
if(ch == '/') return 2;
if(ch == '(') return 0;
if(ch == ')') return 0;
}
int main (){
string str;
string s;
int T ;
cin >> T;
while(T--){
int i=0 ;
str.clear();
s.clear() ;
cin >> str;
stack<char> mid; //字符串栈 ,用于中缀表达式转后缀表达式
stack<double> ans;//数字栈 ,用于后缀表达式求值
while(str[i] != '=')
{
if(str[i] == '('){//判断,左括号进栈
mid.push(str[i]);
i++;
}
else if( str[i] == ')')//遇右括号则将左括号及左括号以上标识符出栈
{
while(mid.top()!='(')
{
s = s + mid.top() ;
s += ' ';
mid.pop() ;
}
mid.pop() ;
i++;
}
else if(isdigit(str[i]))//数字或小数点则直接转入后缀表达式
{
while(str[i]<='9'&&str[i]>='0' || str[i] =='.')
{
s = s + str[i];
i++;
}
s += ' ';
}
else if(str[i] == '+'||str[i] == '-'||str[i] == '*'||str[i] == '/'){
while(!mid.empty() && Judge(mid.top()) >= Judge(str[i])){
//当前运算标识符优先级低于栈顶元素,进行出栈操作
s = s + mid.top();
s = s + ' ';
mid.pop();
}
mid.push(str[i]);//将当前运算符进栈
i++;
}
}
while(!mid.empty())//将最后剩余运算符出栈
{
s = s + mid.top() ;
s = s + ' ';
mid.pop() ;
}
string temp;
stringstream ss(s);
char a[1000];
double num;
while(ss >> temp)//string->char[]
/*
ss.clear();//如果你想通过使用同一stringstream对象实现多种类型的转换,请注意在每一次转换之后都必须调用
*/
{
if( isdigit(temp[0]) ){
for(i=0;i<temp.length();i++)
a[i] = temp[i];
a[i] ='\0';//最后必须赋 '\0' 否则报错
num = atof(a);
//将数字字符串转为数字
//注意atof()函数不支持string类型,支持char()
ans.push(num);//将数字进栈
}
else{// 运算符操作
double x,y;
x = ans.top();
ans.pop();
y = ans.top();
ans.pop();
//取出栈顶两位元素 ,进行相应操作
if(temp == "+") num = x + y;
if(temp == "-") num = y - x;
if(temp == "*") num = x * y;
if(temp == "/") num = y / x;
ans.push(num);//得到元素进栈
}
}
cout<< fixed <<setprecision(2)<<ans.top()<<endl;//输出两位小数;
}
}
//https://blog.csdn.net/F_zmmfs/article/details/81291487
例题:https://pintia.cn/problem-sets/434/problems/5405
注意:运算符优先级相同
逆波兰法:(注:也可以从左到右直接算)
#include <bits/stdc++.h>
using namespace std;
int Judge(char ch){
if(ch == '+') return 1;
else if(ch == '-') return 1;
else if(ch == '*') return 1;
else if(ch == '/') return 1;
else if(ch == '(') return 1;
else if(ch == ')') return 1;
}
string trans(string str){
string s;
stack<char> mid;//存放运算符
int i = 0;
while(str[i] != '='){
if(str[i] == '('){ //判断,左括号进栈
mid.push(str[i]);
i++;
}else if(str[i] == ')'){ //遇右括号则将左括号及左括号以上标识符出栈
while(mid.top() != '('){
s = s + mid.top();
s += ' ';
mid.pop();
}
mid.pop();//左括号出栈
i++;
}else if(isdigit(str[i])){//数字或小数点则直接转入后缀表达式
while(str[i] <= '9' && str[i] >= '0' || str[i] == '.'){
s = s + str[i];
i++;
}
s += ' ';
}else if(str[i] == '+' ||str[i] == '-' ||str[i] == '*' ||str[i] == '/' ){
while(!mid.empty() && Judge(mid.top()) >= Judge(str[i])){
//当运算符优先级低于栈顶元素,出栈操作
s = s + mid.top();
s = s + ' ';
mid.pop();
}
mid.push(str[i]);//当前运算符进栈
i++;
}
}
while(!mid.empty()){//将最后剩余运算符出栈
s = s + mid.top();
s = s + ' ';
mid.pop();
}
return s;
}
void Evaluate(string s){
string temp;
stringstream ss(s);
stack<double> ans;
char a[1000];
double num;
int i;
bool flag = false;
while(ss >> temp){
//将数字字符串转化为数字
if(isdigit(temp[0])){
for( i = 0; i < temp.length(); i++){
a[i] = temp[i];
}
a[i] = '\0';
num = atof(a); //atof()不支持string型,支持char型
ans.push(num); //数字进栈
}else{ //运算符操作
double x, y;
x = ans.top(); ans.pop();
y = ans.top(); ans.pop();
if(temp == "+") num = x + y;
if(temp == "-") num = y - x;
if(temp == "*") num = x * y;
if(temp == "/"){
if(x == 0){
printf("ERROR\n");
return;
}
num = y / x;
}
ans.push(num);
}
}
printf("%d\n", (int)ans.top());
}
bool check(string str){
for(int i = 0; i < str.length(); i++){
if(str[i] >= '0' && str[i] <= '9' || str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/' || str[i] == '.' || str[i] == '='){
}else{
return false;
}
}
return true;
}
int main(){
string str;
cin >> str;
if(check(str)){
Evaluate(trans(str));
}else{
printf("ERROR\n");
}
}