中缀向后缀转换表达式

中缀向后缀转换表达式

题目信息

中缀表达式就是我们通常所书写的数学表达式,后缀表达式也称为逆波兰表达式,在编译程序对我们书写的程序中的表达式进行语法检查时,往往就可以通过逆波兰表达式进行。我们所要设计并实现的程序就是将中缀表示的算术表达式转换成后缀表示,例如,将中缀表达式
(A 一 (B*C 十 D)*E) / (F 十 G )
转换为后缀表示为:
ABC*D十E*--FG十/
注意:为了简化编程实现,假定变量名均为单个字母,运算符只有+,-,*,/ 和^(指数运算),可以处理圆括号(),并假定输入的算术表达式正确。
要求:使用栈数据结构实现 ,输入的中缀表达式以#号结束

输入

整数N。表示下面有N个中缀表达式
N个由单个字母、整数和运算符构成的表达式

输出

N个后缀表达式。

测试样例

测试样例1

1
(A-(B*C+D)*E)/(F+G)#
ABC*D+E*-FG+/

测试样例2

2
a+b*c-d#
a-b*(c+d)#
abc*+d-
abcd+*-

解答

#include <iostream>
#include <stack>
#include <string>
using namespace std;

stack <char> s;

int main()
{
    //freopen("/Users/zhj/Downloads/test.txt","r",stdin);
    int N;
    cin >> N;
    while (N--)
    {
        string in;
        cin >> in;
        int t = 0;
        while (in[t] != '#')
        {
            if (t == 0 && in[t] == '-')
            {//第一个数就是负数
                cout << in[t];
            }
            else if (isalnum(in[t]))
            {//如果是数字字母的话就输出
                cout << in[t];
            }
            else if (in[t] == '(')
            {//是左括号的话就压入栈中
                s.push(in[t]);
            }
            else if (in[t] == ')')
            {//如果是右括号的话,栈元素弹出,将弹出的操作符输出直到遇到左括号为止
                while(s.top()!='(')
                {
                    cout<<s.top();
                    s.pop();
                }
                s.pop();
            }
            else if( in[t] =='-' && ( in[t - 1] == '(' || in[t - 1] == '*' || in[t - 1] == '/' || in[t - 1] == '%' || in[t - 1] == '+' || in[t - 1] == '-') )
            {//此时是负数,且之前的是这些个符号的话,证明当前是一个负数
                cout << in[t];
            }
            else
            {//其他的操作符,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止
                if(s.empty())
                {
                    s.push(in[t]);
                }
                else
                {
                    int x, y;//x=ch,y=top of the stack
                    while (1)
                    {
                        if (s.empty())
                        {
                            s.push(in[t]);
                            break;
                        }

                        char chtmp = s.top();//chtmp此时是栈顶的元素
                        switch (in[t])
                        {//给此时的符号标记一个优先级
                            case '^':{ x = 7; break;}
                                //10^2^2当然便是刚输入这个^优先级别更高,因为后面还可以继续续上^2,变成10^2^2^2
                            case '*':{ x = 4; break;}
                            case '/':{ x = 4; break;}
                            case '+':{ x = 2; break;}
                            case '-':{ x = 2; break;}
                        }
                        switch (chtmp)
                        {//给之前的符号标记一个优先级
                            case '^':{ y = 6; break;}
                            case '*':{ y = 5; break;}
                            case '/':{ y = 5; break;}
                            case '(':{ y = 1; break;}
                            case '+':{ y = 3; break;}
                                //如果之前是一个加号,此时的ch仍然是一个加号,那么理应该输出这个+号的,所以相应的之前的优先级大一点
                            case '-':{ y = 3; break;}
                        }

                        if (y > x || y == x)
                        {//如果原来栈顶的优先级大于之前的优先级,那么就输出
                            cout<<chtmp;
                            s.pop();
                            continue;
                        }
                        else
                        {//不优先说明仍然在累计,则压入栈中
                            s.push(in[t]);
                            break;
                        }
                    }
                }
            }
            t++;
        }
        while (!s.empty())
        {
            cout<<s.top();
            s.pop();
        }
        cout<<endl;
    }
}

总结

本题目主要的点也就是出现在对于负数的处理上面,以下给出一些样例供参考

10
14*10-(10)*2#
14*10-(-10)*2#
14*10--10*2#
-14*-12#
-(1-2*-3)#
-3^-(1-2*-3)#
30/(-3+3)+1#
(-2)--3*(-8)#
-2--3*-8#
-A+B#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhj12399

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值