中缀表达式转换成后缀表达式,进行简单表达式的计算

分析:


  1. 步骤一:中缀表达式转换为后缀表达式

  • 设立一个操作符栈,用来临时存放操作符;设置一个队列用以存放后缀表达式序列。
  • 从左至右遍历中缀表达式,如果遇到操作数(需要注意的是操作数可能不止一位,因此需要一位位的读入然后合并成整数)就将其加入到后缀序列中。
  • 如果遇到操作符,如果是左括号‘(’就直接压入栈中,如果是右括号‘)’就依次弹出栈中元素直至左括号出现。否则将其与栈顶元素比较优先级大小。如果该操作符的优先级更大,那么直接压入栈中。否则每次将栈顶元素弹出,依次加入队列,直至操作符优先级大于了新的栈顶元素的优先级。
  • 重复上述步骤直至遍历完中缀表达式,如果最后栈中还有元素,那么就依次弹出,加入到队列中,直至栈空

  1. 步骤二:计算后缀表达式

从左至右扫描后缀表达式,如果是操作数,那么压入栈中,如果是操作符那么就从栈中弹出两个操作数(注意,这两操作数和操作符的结合顺序是固定的,先弹出的是第二操作数结合到操作符的右边,后弹出的是第一操作数结合到操作符的左边)结合操作符进行运算。并将得到的新的操作数压入到栈中。反复以上步骤直到扫描完后缀表达式。那么最后剩下的就是最终的接过了。


注意:本程序关于括号的处理那一块有问题。我现在还很菜没有找到问题在哪,待以后再改。

#include<iostream>
#include<stack>
#include<queue>
#include<string>
#include<map>
#include<fstream>
using namespace std;
struct node{                //定义结构体,该结构体用于存储每次处理的字符 
    char op;                //如果是操作符,存入到op中,并且要将flag置为false 
    double data;            //如果是操作数,存入到data中,并且要将flag置为true 
    bool flag;
};
stack<node> s;         //操作符栈,存放操作符的临时工作栈。 
queue<node> q;         //后缀表达式队列 
map<char,int> op;      //操作符优先级 
void change(string str){
    op['+']=op['-']=1;                  //输入操作符优先级 
    op['*']=op['/']=2;  
    for(int i=0;i<str.length();){
        node temp;         
        if(str[i]>='0'&&str[i]<='9'){     //如果是操作数的话 
            temp.flag =true;              //标记置为true 
            temp.data=str[i++]-'0';       //存储到临时结构体temp中 
            while(i<str.length() && str[i]>='0' && str[i]<='9'){         //因为数字可能不止一位,因此循环至不是数字为止 
                temp.data=temp.data*10+(str[i]-'0');                     //组成整数 
                i++;
            }
            q.push(temp);                //将该操作数扔进后缀序列的队列中 
        }
        else if(str[i]=='('){          //之前一直以为我这一块处理括号的写错了。。。。。后来发现代码没错。。。是因为自己输入的是中文括号。。。
            temp.flag =false;
            temp.op =str[i];             //是左括号直接压入队列 
            s.push(temp); 
            i++;
        }
        else if(str[i]==')'){            //终于等到了右括号 
            while(s.top().op!='('){      //将栈里面的操作符弹出到后缀表达式中,知道碰到了左括号 
                q.push(s.top());
                s.pop();                 
            }
            s.pop() ;                     //扔掉左括号 
            i++;
        } 
        else{
            temp.flag =false;              //如果是操作符,那么标记置为false 
            while(!s.empty()&&op[str[i]]<=op[s.top().op]){      //只有当该操作符的优先级高于栈顶元素的优先级,才压入栈内 
                q.push(s.top());                                //否则将栈顶元素弹出,压入到队列中 
                s.pop() ; 
            }
            temp.op=str[i];                  
            s.push(temp);
            i++; 
        }

    }
    while(!s.empty()){                 //最后如果操作符栈还不空的话。依次弹出压入到队列中 
            q.push(s.top());
            s.pop() ; 
        }
}
double cal(){                  //计算后缀表达式 
    node cur,temp;
    double temp1,temp2;        //第一操作数,第二操作数 
    while(!q.empty()){
        cur=q.front();         //取得队首元素 
        q.pop() ;             
        if(cur.flag==true){   //如果是操作数,压入栈中 
            s.push(cur); 
        }
        else{                    //如果是操作符 
            temp2=s.top().data ;  //取出第二操作数 
            s.pop() ;
            temp1=s.top().data ;  //取出第一操作数 
            s.pop() ;
            temp.flag =true;      //临时存放结果的temp,当然是新的操作数 
            if(cur.op =='+'){
                temp.data =temp1+temp2;
            }
            else if(cur.op =='-'){
                temp.data =temp1-temp2;
            }
            else if(cur.op =='*'){
                temp.data =temp1*temp2;
            }
            else{
                temp.data =temp1/temp2;
            }
            s.push(temp); 
        }
    }
    return s.top().data;         //最后栈顶剩的唯一一个元素就是最终的结果了 
}

int main()
{
    string str;
    //fstream fin("C://Users/haha/Desktop/input.txt",ios::in);      //笔者当时从文件中读取的表达式 
    cin>>str;
    change(str);      //改成后缀表达式 
    cout<<cal();      //计算结果。    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值