逆波兰表达式(中序表达式转后序表式式)

逆波兰表达式(中序表达式转后序表式式)

目录:

  • 逆波兰表达式中序表达式转后序表式式
    • 简单技巧
    • 算法
    • 测试代码

简单技巧:

中序表达式转后序表式式:

将中序表达式所有括号补全,然后将所有运算符向右移出无匹配的第一个右括号,去掉括号即为后序表式式

举例:
原式:a+b*(c+d/e)
补全括号:(a+(b*(c+(d/e))))
操作符右移:(a(b(c(de)/)+)*)+
去掉括号:abcde/+*+

中序表达式转前序表式式:

将中序表达式所有括号补全,然后将所有运算符向左移出无匹配的第一个左括号,去掉括号即为前序表式式

举例:
原式:a+b*(c+d/e)
补全括号:(a+(b*(c+(d/e))))
操作符右移:+(a*(b+(c/(de))))
去掉括号:+a*b+c/de

算法:

利用运算符栈(OPTR)和数据栈(OPND)将中缀表达式转化为后缀表达式。

将结束标志字符’#’放入操作符栈(OPTR);
从中缀表达式pre左端依次读取pre[i]:

  • 1.若pre[i]为操作数,压入数据栈(OPND);
  • 2.若pre[i]为左括号,压入操作符栈(OPTR);
  • 3.若pre[i]为右括号,则将操作符栈(OPTR)中的运算符依次出栈并压入数据栈(OPND),直到遇到左括号为止,但是该左括号出栈但不压入数据栈(OPND)
  • 4.若pre[i]为操作符:
    (1)若操作符栈(OPTR)为空,将此操作符pre[i]压入数据栈(OPND);
    (2)若pre[i]的优先级大于操作符栈(OPTR)顶的优先级,将此操作符pre[i]压入数据栈(OPND);
    (3)若操作符栈(OPTR)不为空且pre[i]的优先级小于等于操作符栈(OPTR)顶的优先级,将操作符栈(OPTR)中的运算符依次出栈并压入数据栈(OPND),直到不满足条件,此操作符pre[i]压入数据栈(OPND)

直到遍历完整个中序表达式之后,操作符栈(OPTR)中仍然存在运算符,那么将这些运算符依次出栈加入到数据栈(OPND)中,直到栈为空。

按照上述步骤完成后,将操作符栈(OPTR)逆序即可得到逆波兰表达式。

  • 判断是否为运算符
bool isoperator(char op)
{
    switch(op)
    {
    case '+':
    case '-':
    case '*':
    case '/':
        return 1;
    default :
        return 0;
    }
}
  • 优先级
int priority(char op)
{
    switch(op)
    {
    case '#':
        return -1;
    case '(':
        return 0;
    case '+':
    case '-':
        return 1;
    case '*':
    case '/':
        return 2;
    default :
        return -1;
    }
}
  • 把中缀表达式转换为后缀表达式
//把中缀表达式转换为后缀表达式
void postfix(char pre[])
{
    int i = 0;
    stack<char> OPTR;   //运算符栈
    stack<char> OPND;   //数据栈

    OPTR.push('#');    // 首先把结束标志‘#’放入栈底
    while(pre[i]!='#')
    {
        if((pre[i]>='a' && pre[i] <='z')) // 遇到点直接写入后缀表达式
        {
            OPND.push(pre[i]);
        }
        else if (pre[i]=='(')    // 遇到“(”不用比较直接入栈
            OPTR.push(pre[i]);
        else if(pre[i] ==')')  // 遇到右括号将其对应左括号后的操作符(操作符栈中的)全部写入后缀表达式
        {
            while(OPTR.top()!='(')
            {
                OPND.push(OPTR.top());
                OPTR.pop();
            }
            OPTR.pop(); // 将“(”出栈,后缀表达式中不含小括号
        }
        else if (isoperator(pre[i]))
        {
            while(!OPTR.empty() && priority(pre[i]) <= priority(OPTR.top()))
            {
                // 当前的操作符小于等于栈顶操作符的优先级时,将栈顶操作符写入到后缀表达式,重复此过程
                OPND.push(OPTR.top());
                OPTR.pop();
            }
            OPTR.push(pre[i]);    // 当前操作符栈为空或者当前操作符优先级大于栈顶操作符的优先级,将该操作符入栈
        }

        i++;
    }
    while(OPTR.top() != '#') // 将所有的操作符加入后缀表达式
    {
        OPND.push(OPTR.top());
        OPTR.pop();
    }
    OPTR.pop();

    //利用操作符栈逆序即可得到后缀表达式
    while(!OPND.empty())
    {
        OPTR.push(OPND.top());
        OPND.pop();
    }
    while(!OPTR.empty())
    {
        cout << OPTR.top();
        OPTR.pop();
    }
    cout << endl;
}

测试代码

#include <iostream>
#include <vector>
#include <cstring>
#include <stack>
using namespace std;

bool isoperator(char op);       // 判断是否为运算符
int priority(char op);          // 求运算符优先级
void postfix(char pre[]);       // 把中缀表达式转换为后缀表达式

int main()
{
    char exp[100];
    char post[100];
    memset(post, '\0', sizeof(exp));
    cin >> exp;

    postfix(exp);
    return 0;
}

bool isoperator(char op)
{
    switch(op)
    {
    case '+':
    case '-':
    case '*':
    case '/':
        return 1;
    default :
        return 0;
    }
}


int priority(char op)
{
    switch(op)
    {
    case '#':
        return -1;
    case '(':
        return 0;
    case '+':
    case '-':
        return 1;
    case '*':
    case '/':
        return 2;
    default :
        return -1;
    }
}

//把中缀表达式转换为后缀表达式
void postfix(char pre[])
{
    int i = 0;
    stack<char> OPTR;   //运算符栈
    stack<char> OPND;   //数据栈

    OPTR.push('#');    // 首先把结束标志‘#’放入栈底
    while(pre[i]!='#')
    {
        if((pre[i]>='a' && pre[i] <='z')) // 遇到点直接写入后缀表达式
        {
            OPND.push(pre[i]);
        }
        else if (pre[i]=='(')    // 遇到“(”不用比较直接入栈
            OPTR.push(pre[i]);
        else if(pre[i] ==')')  // 遇到右括号将其对应左括号后的操作符(操作符栈中的)全部写入后缀表达式
        {
            while(OPTR.top()!='(')
            {
                OPND.push(OPTR.top());
                OPTR.pop();
            }
            OPTR.pop(); // 将“(”出栈,后缀表达式中不含小括号
        }
        else if (isoperator(pre[i]))
        {
            while(!OPTR.empty() && priority(pre[i]) <= priority(OPTR.top()))
            {
                // 当前的操作符小于等于栈顶操作符的优先级时,将栈顶操作符写入到后缀表达式,重复此过程
                OPND.push(OPTR.top());
                OPTR.pop();
            }
            OPTR.push(pre[i]);    // 当前操作符栈为空或者当前操作符优先级大于栈顶操作符的优先级,将该操作符入栈
        }

        i++;
    }
    while(OPTR.top() != '#') // 将所有的操作符加入后缀表达式
    {
        OPND.push(OPTR.top());
        OPTR.pop();
    }
    OPTR.pop();

    //利用操作符栈逆序即可得到后缀表达式
    while(!OPND.empty())
    {
        OPTR.push(OPND.top());
        OPND.pop();
    }
    while(!OPTR.empty())
    {
        cout << OPTR.top();
        OPTR.pop();
    }
    cout << endl;
}

你可能感兴趣的:(逆波兰表达式(中序表达式转后序表式式))