逆波兰算法

中缀表达式转后缀表达式

栈实现

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");
    }


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值