前缀、中缀、后缀表达式归纳

后缀表达式求值:

后缀表达式是无需进行处理可以直接被计算机处理的表达式,运算符通常位于操作数的后面,例如: 3 4 + 5 * 6 -   ,它是由中缀表达式(3 + 4) × 5 - 6转换过来的

后缀表达式进行求值时,设立一个栈s1,从左到右依次访问表达式中的元素,如果遇到数字直接压入栈中,如果遇到运算符就将栈中最上方的两个元素取出后进行相应的运算,将运算结果压入栈中。具体c++代码如下:

#include <iostream>
#include <stack>
#include <string>

using namespace std;

int main()
{
    string s;
    getline(cin,s);        //这里需要注意,因为输入的后缀表达式操作数与运算符之间有空格隔开,因此不能用cin或者scanf进行读入
    int len = s.size();     // cin或者scanf读入时,遇到空格就会判定为结束
    int a,b;
    stack<int> t;
    int i;
    for (i = 0;i < len;i++)
    {
        if (s[i] == '+' ||s[i] == '-' ||s[i] == '*' ||s[i] == '/' )
        {
            if (s[i] == '+')
            {
                a = t.top();
                t.pop();
                b = t.top();
                t.pop();
                a = a + b;
                t.push(a);
            }
            else if (s[i] == '-')
            {
                a = t.top();
                t.pop();
                b = t.top();
                t.pop();
                a = b - a;
                t.push(a);
            }
            else if (s[i] == '*')
            {
                a = t.top();
                t.pop();
                b = t.top();
                t.pop();
                a = a * b;
                t.push(a);
            }
            else if (s[i] == '/')
            {
                a = t.top();
                t.pop();
                b = t.top();
                t.pop();
                a = b / a;
                t.push(a);
            }
            i++;
        }
        else
        {
            int sum = 0;
            while (s[i] != ' ')
            {
                sum *= 10;
                sum += (s[i] - '0');
                i++;
            }
            t.push(sum);
        }
    }
    cout << t.top() << endl;
}


中缀表达式转换成后缀表达式


中缀表达式在求值时往往要先转换成相对应的后缀表达式,具体的做法是

1.设立两个栈t1,t2,分别用来存放运算符和操作数

2.从左至右扫描中缀表达式;

3.遇到操作数时,将其压入t2;
4.遇到运算符时,进行如下处理:
4-1.如果t1为空,或栈顶运算符为左括号“(”,或者该运算符为'(',则直接将此运算符入栈;
4-2.如果运算符为‘)’,那么依次将t1中的运算符弹出,压入t2,直到遇到一个‘(’,将它消除;

4-3.否则,将它与栈顶的运算符的优先级进行比较:

4-3-1.如果它的优先级大于栈顶运算符优先级,那么直接压入t1;

4-3-2.如果它的优先级小于栈顶运算符优先级,那么依次将t1中的运算符弹出,压入t2,直到遇见比它优先级小的,或者栈空,或者遇到‘(’,将它压入t1;

5.依次遍历完整个中缀表达式,栈t2中存放的就是所求的后缀表达式;

#include <iostream>
#include <stack>
#include <vector>

using namespace std;

bool judge1(char s)
{
    if (s == '+' || s == '-' || s == '*' || s == '/' || s == '(' || s == ')') return true;
    else return false;
}

int getOp (char s)
{
    if (s == '+') return 0;
    else if (s == '-') return 1;
    else if (s == '*') return 2;
    else if (s == '/') return 3;
}

int op[4][4] = {0,0,0,0,
                0,0,0,0,
                1,1,0,0,
                1,1,0,0};

bool judge2(char a,char b)
{
    int op1 = getOp(a);
    int op2 = getOp(b);
    if (op[op1][op2] == 1) return true;
    else return false;
}

int main()
{
    char k;
    vector<char> s;
    while (scanf("%c",&k) != '\n')     //这里其实有个很严重的错误,在读入中缀表达式的时候,操作数和运算符之间是有空格的,因此不能用cin或者是scanf
    {
        s.push_back(k);                // 而必须使用getline()或者是gets() , 不过我懒得改了,具体可以参考上面的后缀表达式求值 
    }
    int len = s.size();  
    stack<char> t1;
    stack<char> t2;
    for (int i = 0;i < len;i++)
    {
        bool temp1 = judge1(s[i]);
        if (!temp1)
        {
            t2.push(s[i]);
        }
        else
        {
            if (s[i] == '(' || t1.empty() || t1.top() == '(')
            {
                t1.push(s[i]);
            }
            else if(s[i] == ')')
            {
                while (t1.top() != '(')
                {
                    char ex = t1.top();
                    t2.push(ex);
                    t1.pop();
                }
                t1.pop();
            }
            else
            {
                bool temp2 = judge2(s[i],t1.top());
                if (temp2)
                {
                    t1.push(s[i]);
                }
                else
                {
                    while (!t1.empty() && !judge2(s[i],t1.top()) && t1.top() != '(')
                    {
                        char tt = t1.top();
                        t2.push(tt);
                        t1.pop();
                    }
                    t1.push(s[i]);
                }
            }
        }
    }
    while (!t1.empty())
    {
        char xx = t1.top();
        t2.push(xx);
        t1.pop();
    }
    stack<char> out;
    while (!t2.empty())
    {
        char xx = t2.top();
        out.push(xx);
        t2.pop();
    }
    while (!out.empty())
    {
        cout << out.top();
        out.pop();
    }
    cout << endl;
}

前缀表达式求值:

前缀表达式求值和后缀表达式求值方法很相似,只不过前缀表达式求值是从右往左扫描表达式,遇到操作数则压入栈中,遇到运算符则弹出两个操作数计算结果后重新压入

中缀表达式转前缀表达式:

与中缀转后缀相似,只说明一下不同点:

1.中缀转前缀是从右到左扫描

2.在中缀转后缀中,如果运算符比栈顶运算符的优先级高,则压入栈中,否则要依次弹出运算符栈中的元素,直到栈顶元素优先级比它低;而在中缀转前缀时,这一规则改变为如 果运算符比栈顶运算符的优先级高或它们的优先级相等,则压入栈中。















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值