【数据结构】C++将一个书写正确的表达式转换为逆波兰式

题目:设表达式由单字母变量、双目运算符和圆括号组成(如:“(a*(b+c)-d)/e)”。试写一个算法,将一个书写正确的表达式转换为逆波兰式。

步骤思路:

(1)首先,需要分配2个栈,栈s1用于临时存储运算符(含一个结束符号),此运算符在栈内遵循越往栈顶优先级越高的原则;栈s2用于输入逆波兰式,为方便起见,栈s1需先放入一个优先级最低的运算符,在这里假定为'#';

(2)从中缀式的左端开始逐个读取字符x,逐序进行如下步骤:

   1.若x是操作数,则分析出完整的运算数(在这里为方便,用字母代替数字),将x直接压入栈s2;

   2.若x是运算符,则分情况讨论:

  •                         ①若x是'(',则直接压入栈s1;
  •                       ②若x是')',则将距离栈s1栈顶的最近的'('之间的运算符,逐个出栈,依次压入栈s2,此时抛弃'(';
  •                         ③若x是除'('和')'外的运算符,则再分如下情况讨论:
    •                                 ③-1若当前栈s1的栈顶元素为'(',则将x直接压入栈s1;
      •                                ③-2若当前栈s1的栈顶元素不为'(',则将x与栈s1的栈顶元素比较,若x的优先级大于栈s1栈顶运算符优先级,则将x直接压入栈s1。否者,将栈s1的栈顶运算符弹出,压入栈s2中,直到栈s1的栈顶运算符优先级别低于(不包括等于)x的优先级,或栈s2的栈顶运算符为'(',此时再则将x压入栈s1;

 (3)在进行完(2)后,检查栈s1是否为空,若不为空,则将栈中元素依次弹出并压入栈s2中(不包括'#');      

 (4)完成上述步骤后,栈s2便为逆波兰式输出结果。但是栈s2应做一下逆序处理,因为此时表达式的首字符位于栈底;

代码实现:

#include <stack>
#include <iostream>
#include <string.h>
#include <algorithm>

using namespace std;

bool compare_precedence(char a, char b);
string RPN(string expression);

int main()
{
    cout <<"Please input the normal expression:" <<endl;
    string expression;
    cin >> expression;
    string RPN_result = RPN(expression);
    cout <<"The RPN of expression is: \n"<< RPN_result <<endl;
    return 0;
}

string RPN(string expression){
    stack<char> s1;//临时存储运算符
    s1.push('#');
    stack<char> s2;//输入逆波兰式
    for (decltype(expression.size()) index = 0; index != expression.size(); index++){
        char x = expression[index];
        if((x>='a'&& x<='z') || (x>='A' && x<='Z')){
            s2.push(x);
            continue;
        }
        else if(x=='('){
            s1.push(x);
            continue;
        }
        else if(x==')'){
            while(s1.top()!='('){
                s2.push(s1.top());
                s1.pop();
            }
            if(!s1.empty() && s1.top()=='(')
                s1.pop();
            continue;
        }
        else{
            if(s1.top()=='('){
                s1.push(x);
                continue;
            }
            else{
                while((!compare_precedence(x,s1.top())) && s1.top()!='('){
                    s2.push(s1.top());
                    s1.pop();
                }
                s1.push(x);
                continue;
            }
        }
    }
    if(!s1.empty()){
        while(s1.top()!='#'){
            s2.push(s1.top());
            s1.pop();
        }
    }
    string result;
    for (int index = 0; !s2.empty(); index++){
        result = result + (string(1,s2.top()));
        s2.pop();
    }
    reverse(result.begin(), result.end());
    return result;
}

//比较a的优先级是否大于b,若是则返回true,否则返回false
bool compare_precedence(char a, char b){
    if(b=='#')
        return true;
    else if(a=='*'||a=='/'||a=='%'){
        if(b=='+'||b=='-')
            return true;
        else
            return false;
    }
    else if(a=='+'||a=='-'){
        return false;
    }
    else{printf("Operator compare error!"); return -1;}
}

测试:

用例

输出

结果

((a+b)*c-d)/h+v%e

a+b/c*(d+f)-m

猜你喜欢

转载自blog.csdn.net/standingflower/article/details/127581291