中缀转前缀和后缀表达式及计算

中缀转前缀和后缀表达式及计算

1 中缀转前缀

算法思想:表达式中的对象为操作数和运算符,因此需要维护两个栈表:运算符栈和操作数(中间运算结果)栈,具体算法步骤如下。

  • (1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2
  • (2) 从右至左扫描中缀表达式;
  • (3) 遇到操作数时,将其压入S2
  • (4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
  • (4-1) 如果S1为空,或栈顶运算符为右括号),则直接将此运算符入栈;
  • (4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1
  • (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
  • (5) 遇到括号时:
  • (5-1) 如果是右括号),则直接压入S1
  • (5-2) 如果是左括号(,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃;
  • (6) 重复步骤(2)至(5),直到表达式的最左边;
  • (7) 将S1中剩余的运算符依次弹出并压入S2
  • (8) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。
#include 
#include 
#include 
#include 
#include
using namespace std;

stack<char> q1;  // 运算符号栈
stack<char> q2;  // 答案栈

// 判断优先级函数
bool y(char a1,char a2){
    if(a1=='+'||a1=='-'){  //优先级判断1
        if(a2==')'||a2 == '+'||a2 == '-')
        return true;
        else return false;
    }
      else if(a1=='*'||a1=='/'||a1=='%')  //优先级判断2
      return true;
    
    return false;
}

//弹出函数
void se(){

                //如果是左括号,开始弹出两个括号之间多有的内容
        while(1){
            if(q1.top()!='('&&q1.top()!=')'){
                q2.push(q1.top());
            }
             if(q1.top()==')'||q1.empty())break;
             q1.pop();  //弹出操作
        } 
        if(q1.top()==')')q1.pop();  //将最后一个右括号也弹出

}

int main(int argc, const char * argv[]) {

       string s1 ;
       cin>>s1;
     
        for(int i = s1.size()-1;i>=0;i--){
            
         if(s1[i]>='0'&&s1[i]<='9')q2.push(s1[i]);
         else{
             if(q1.size()==0||q1.top()==')'||s1[i]==')')q1.push(s1[i]); //如果是空或者右括号,直接压入q1栈
             else if(s1[i]=='('){q1.push(s1[i]);se();}     // 如果是左括号,先压入栈,然后开始找右括号
             else if(y(s1[i],q1.top()))q1.push(s1[i]);     // 如果优先级高,直接压入栈
             else {
                 while(!q1.empty()&&!y(s1[i],q1.top())){   //优先级低 开始一个一个弹出栈
              if(q1.empty()||q1.top()==')'||q1.top()=='(')break;
                 q2.push(q1.top());
                 q1.pop();
             }
             q1.push(s1[i]);  //最后还得把这个操作符入栈
             }
             
         }
        }
        //最后q1栈如果不是空,把剩余的非括号都压入栈
        while(!q1.empty()){
            if(q1.top()!='('&&q1.top()!=')')
            q2.push(q1.top());
            q1.pop();
    
        }

        //遍历q2栈
        while(!q2.empty()){
            cout<<q2.top();
            q2.pop();
        }
      cout<<endl;
    return 0;
}

2 中缀转后缀

与转换为前缀表达式相似,遵循以下步骤:

  • (1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2
  • (2) 从左至右扫描中缀表达式;
  • (3) 遇到操作数时,将其压入S2
  • (4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
  • (4-1) 如果S1为空,或栈顶运算符为左括号(,则直接将此运算符入栈;
  • (4-2) 否则,若优先级比栈顶运算符的高,也将运算符压入S1(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况);
  • (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
  • (5) 遇到括号时:
  • (5-1) 如果是左括号(,则直接压入S1
  • (5-2) 如果是右括号),则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃;
  • (6) 重复步骤(2)至(5),直到表达式的最右边;
  • (7) 将S1中剩余的运算符依次弹出并压入S2
  • (8) 依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)。
//
//  main.cpp
//  step1
//
//  Created by ljpc on 2018/8/31.
//  Copyright © 2018年 ljpc. All rights reserved.
//

#include 
#include 
#include 
#include 
#include
using namespace std;

stack<char> q1;  // 运算符号栈
stack<char> q2;  // 答案栈

bool y(char a1,char a2){
    if(a1=='+'||a1=='-'){  //优先级判断1
        if(a2=='(')
        return true;
        else return false;
    }
      else if(a1=='*'||a1=='/'||a1=='%') { //优先级判断2
      if(a2 == '+'||a2 == '-')
      return true;
      }
    return false;
}

void se(){

                //如果是左括号,开始弹出两个括号之间多有的内容
        while(1){
            if(q1.top()!=')'&&q1.top()!='('){
                q2.push(q1.top());
            }
             if(q1.top()=='('||q1.empty())break;
             q1.pop();  //弹出操作
        } 
        if(q1.top()=='(')q1.pop();  //将最后一个左括号也弹出

}

int main(int argc, const char * argv[]) {

       string s1 ;
       cin>>s1;
     
        for(int i = 0 ;i<s1.size();i++){
            
         if(s1[i]>='0'&&s1[i]<='9')q2.push(s1[i]);
         else{
             if(q1.size()==0||q1.top()=='('||s1[i]=='(')q1.push(s1[i]); //如果是空或者左括号,直接压入q1栈
             else if(s1[i]==')'){q1.push(s1[i]);se();}     // 如果是左括号,先压入栈,然后开始找右括号
             else if(y(s1[i],q1.top()))q1.push(s1[i]);     // 如果优先级高,直接压入栈
             else {
                 while(!q1.empty()&&!y(s1[i],q1.top())){   //优先级低 开始一个一个弹出栈
              if(q1.empty()||q1.top()=='('||q1.top()==')')break;
                 q2.push(q1.top());
                 q1.pop();
             }
             q1.push(s1[i]);  //最后还得把这个操作符入栈
             }
             
         }
        }
        //最后q1栈如果不是空,把剩余的非括号都压入栈
        while(!q1.empty()){
            if(q1.top()!='('&&q1.top()!=')')
            q2.push(q1.top());
            q1.pop();
    
        }

        //遍历q2栈
        char arr[1000] ={0};
        int l = q2.size();
        int i=0;
        while(!q2.empty()){
            arr[i++] = q2.top();
            q2.pop();
        }
        for(int i=l-1;i>=0;i--)cout<<arr[i];
      cout<<endl;

 
    return 0;
}

3 计算前缀表达式

算法思想:从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 - 运算符 - 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。可见用计算机计算前缀表达式的值是非常容易的。

例如前缀表达式- * + 3 4 5 6

(1) 从右至左扫描,将6、5、4、3压入堆栈; (2) 遇到+运算符,因此弹出34(注意3为栈顶元素,4为次顶元素),计算出3+4的值,得7,再将7入栈; (3) 接下来是*运算符,因此弹出75,计算出7*5=35,将35入栈; (4) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。

#include 
#include 
#include 
#include 
#include
using namespace std;

stack<string> q;
string s;

// 计算运算结果
string yun(int a1,int a2,char s1){
    if(s1=='+')return  to_string(a1+a2);
    else if(s1=='-')return  to_string(a1-a2);
    else if(s1=='*')return to_string(a1*a2);

}

//压入栈
void se(char s1){
    int q1 = stoi(q.top());
    q.pop();
    int q2 = stoi(q.top());
    q.pop();
    string q3 = yun(q1,q2,s1);
    q.push(q3);
    
}

int main(int argc, const char * argv[]) {

    
     cin>>s;
     for(int i=s.size()-1;i>=0;i--){
        if(s[i]==')'||s[i]=='(')continue;
         else if(s[i]>='0'&&s[i]<='9'){string d ;d+=s[i] ;q.push(d);} //用字符串的形式来储存元素
         else se(s[i]);
     }
     
         cout<<q.top()<<endl;

    
    return 0;
}

4 计算后缀表达式

算法思想:与前缀表达式类似,从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 - 运算符 - 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。

例如后缀表达式3 4 + 5 * 6 -: (1) 从左至右扫描,将34压入堆栈; (2) 遇到+运算符,因此弹出43(注意4为栈顶元素,3为次顶元素,注意与前缀表达式做比较),计算出3+4的值,得7,再将7入栈; (3) 将5入栈; (4) 接下来是*运算符,因此弹出57,计算出7*5=35,将35入栈; (5) 将6入栈; (6) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。

#include 
#include 
#include 
#include 
#include
using namespace std;

stack<string> q;
string s;


string yun(int a1,int a2,char s1){
    if(s1=='+')return  to_string(a1+a2);
    else if(s1=='-')return  to_string(a2-a1);
    else if(s1=='*')return to_string(a1*a2);

}

void se(char s1){
    int q1 = stoi(q.top());
    q.pop();
    int q2 = stoi(q.top());
    q.pop();
    string q3 = yun(q1,q2,s1);
    q.push(q3);
    
}


int main(int argc, const char * argv[]) {

   
    
     cin>>s;
     for(int i=0;i<s.size();i++){
        if(s[i]==')'||s[i]=='(')continue;
         else if(s[i]>='0'&&s[i]<='9'){string d ;d+=s[i] ;q.push(d);}
         else se(s[i]);
     }
     
         cout<<q.top()<<endl;
  
    
    return 0;
}

你可能感兴趣的:(#STL,c++,算法,c++,数据结构)