【PTA】后缀表达式 (中缀表达式转化为后缀表达式)

  

目录

1.题目描述

2.输入输出

3.解题思路

4.样例解析 

5.代码实现

1.题目描述

所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右进行(不用考虑运算符的优先级)。

如:中缀表达式 3*(5–2)+7 对应的后缀表达式为:352-*7+ 。

请将给出的中缀表达式转化为后缀表达式并输出。


 2.输入输出


输入样例: 

2+4*8+(8*8+1)/3

输出样例:

248*+88*1+3/+


 3.解题思路

对于中缀表达式转换为后缀表达式,我们需要用以下步骤来解决这个问题:

  1. 初始化一个个栈:运算符栈S1
  2. 从左往右开始扫描中缀表达式
    1. 遇到数字,直接输出
    2. 遇到运算符:
      1. 若为 '('  直接入栈
      2. 若为 ')'  将符号栈中的元素依次出栈并输出,直到 '(', '(' 只出栈,不输出
      3. 若为其他符号,将符号栈中的元素依次出栈并将其输出,直到遇到比当前符号优先级更低的符号或者 '('。将当前符号入栈。
      4. 扫描完后,将栈中剩余的符号依次输出。

4.样例解析 

下面以 a + b * c +(d * e + f) * g 为例子来讲讲计算机的转换过程。

1.从左向右开始遍历表达式,首先遇到a, 直接将其输出

    此时输出 :a

    栈的情况:空

2.继续遍历表达式,遇到+,此时栈空,则将其放入栈中

    此时输出 :a

    栈的情况:+

3.继续遍历表达式,遇到b,直接将其输出

    此时输出 :a b

    栈的情况:+

4.继续遍历表达式,遇到*,因为*的优先级大于栈顶的+,所以将*入栈

    此时输出 :a b

    栈的情况:+*

5.继续遍历表达式,遇到c,直接将其输出

    此时输出 :a b c

    栈的情况:+*

6.继续遍历表达式,遇到+, 因为+的优先级低于栈顶的*,所以将栈顶的*弹出;然后新的栈顶元素的+与当前的+优先级相同,所以也要将+弹出;然后栈空了,将现在这个+放入栈中

    此时输出 :a b c * + 

    栈的情况:+

7.继续遍历表达式,遇到(,直接将其放入栈中,不遇到)不会将(弹出。

     此时输出为:a b c * + 

     栈的情况为:+(

8.继续遍历表达式,遇到d,直接将其输出

     此时输出为:a b c * + d

     栈的情况为:+(

9.继续遍历表达式,遇到*,因为栈顶为(,不遇到)不将(弹出,故直接将*放入栈中。

       此时输出为:a b c * + d

       栈的情况为:+(*

10.继续遍历表达式,遇到e,直接将其输出

       此时输出为:a b c * + d e

       栈的情况为:+(*

11.继续遍历表达式,遇到+,因为+比栈顶*的优先级低,故将*弹出;新的栈顶元素为(,不遇到)不弹出(,故将+放入栈中。

此时输出为:a b c * + d e *

栈的情况为:+(+

12.继续遍历表达式,遇到f,直接将其输出

      此时输出为:a b c * + d e *  f

      栈的情况为:+(+

13.继续遍历表达式,遇到),直接将栈中元素依次弹出并输出直到遇到(为止,注意:(弹出但不输出

       此时输出为:a b c * + d e *  f + 

       栈的情况为:+

14.继续遍历表达式,遇到*,因为*的优先级大于栈顶元素+的优先级,故直接将*入栈。

        此时输出为:a b c * + d e *  f + 

        栈的情况为:+ * 

15.继续遍历表达式,遇到g,直接将其输出。

        此时输出为:a b c * + d e *  f + g

        栈的情况为:+ * 

16.继续遍历表达式,为空,遍历结束。将栈内元素依次弹出。

        此时输出为:a b c * + d e *  f + g * +

        栈的情况为:空

至此,中缀表达式转后缀已经全部完成,结果为 a b c * + d e *  f + g * +


5.代码实现

   5.1.优先级确认

int priority(char op)
{
    int priority;
    if(op == '*' || op == '/') priority = 2;
    if(op == '+' || op == '-') priority = 1;
    if(op == '(') priority = 0;
    return priority;
}

     5.2.转换函数

//引用符号提高转换效率
void Trans(string &str, string &str1)
{
    stack<char> s;
    int i;
    for(i = 0; i < str.size(); i ++ )
    {
        //是数字的情况下直接输出
        if(str[i] >= '0' && str[i] <= '9' || str[i] >= 'a' && str[i] <= 'z')
        {
            str1 += str[i];
        }
        else //不是数字的情况分类讨论进行判断
        {
            //栈为空时直接入栈
            if(s.empty()) s.push(str[i]);
            //左括号入栈
            else if(str[i] == '(') s.push(str[i]);
            //如果是右括号,只要栈顶不是左括号,就弹出并输出
            else if(str[i] == ')')
            {
                while(s.top() != '(')
                {
                    str1 += s.top();
                    s.pop();
                }
                //弹出左括号,但不输出
                s.pop();
            }
            else 
            {
                //栈顶元素的优先级大于等于当前的运算符,就将其输出
                while(priority(str[i]) <= priorty(s.top()))
                {
                    str1 += s.top();
                    s.pop();
                    //栈为空,停止
                    if(s.empty()) break;
                }
                s.push(str[i]);
            }
        }
    }
    //最后,如果不为空,就把所以的元素全部弹出
    while(!s.empty())
    {
        str1 += s.top(); 
        s.pop();
    }
}

#include <iostream>
#include <cstring>
#include <stack>

using namespace std;

int priority(char op)
{
    int priority;
    if(op == '*' || op == '/') priority = 2;
    if(op == '+' || op == '-') priority = 1;
    if(op == '(') priority = 0;
    return priority;
}

//引用符号提高转换效率
void Trans(string &str, string &str1)
{
    stack<char> s;
    int i;
    for(i = 0; i < str.size(); i ++ )
    {
        //是数字的情况下直接输出
        if(str[i] >= '0' && str[i] <= '9' || str[i] >= 'a' && str[i] <= 'z')
        {
            str1 += str[i];
        }
        else //不是数字的情况分类讨论进行判断
        {
            //栈为空时直接入栈
            if(s.empty()) s.push(str[i]);
            //左括号入栈
            else if(str[i] == '(') s.push(str[i]);
            //如果是右括号,只要栈顶不是左括号,就弹出并输出
            else if(str[i] == ')')
            {
                while(s.top() != '(')
                {
                    str1 += s.top();
                    s.pop();
                }
                //弹出左括号,但不输出
                s.pop();
            }
            else 
            {
                //栈顶元素的优先级大于等于当前的运算符,就将其输出
                while(priority(str[i]) <= priorty(s.top()))
                {
                    str1 += s.top();
                    s.pop();
                    //栈为空,停止
                    if(s.empty()) break;
                }
                s.push(str[i]);
            }
        }
    }
    //最后,如果不为空,就把所以的元素全部弹出
    while(!s.empty())
    {
        str1 += s.top(); 
        s.pop();
    }
}

int main()
{
    //输入前缀表达式
    string infix;
    string postfix;
    cin >> infix;
    
    Trans(infix, postfix);
    
    cout << postfix << endl;
    return 0;
}
  • 71
    点赞
  • 117
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 43
    评论
中缀表达式转化后缀表达式的步骤如下: 1. 初始化一个空栈和一个空后缀表达式。 2. 从左到右扫描中缀表达式的每个元素。 3. 如果当前元素是操作数,则将其添加到后缀表达式的末尾。 4. 如果当前元素是左括号,则将其压入栈中。 5. 如果当前元素是右括号,则将栈中的元素弹出并添加到后缀表达式中,直到遇到左括号。左括号不会被添加到后缀表达式中,也不会被弹出。 6. 如果当前元素是运算符,则比较其与栈顶运算符的优先级。如果当前运算符的优先级小于或等于栈顶运算符的优先级,则将栈顶运算符弹出并添加到后缀表达式中,直到当前运算符的优先级大于栈顶运算符的优先级或栈为空,然后将当前运算符压入栈中。 7. 重复步骤2至6,直到扫描完整个中缀表达式。 8. 如果栈中还有元素,则将它们依次弹出并添加到后缀表达式中。 例如,将中缀表达式 - + 6 * 3 - 7 4 / 8 2 转化后缀表达式的过程如下: - 首先,初始化一个空栈和一个空后缀表达式。 - 从左到右扫描中缀表达式的每个元素: - 第一个元素是减号,是运算符,将其压入栈中。 - 第二个元素是加号,是运算符,由于栈为空,将其压入栈中。 - 第三个元素是数字6,是操作数,将其添加到后缀表达式的末尾。 - 第四个元素是乘号,是运算符,将其压入栈中。 - 第五个元素是数字3,是操作数,将其添加到后缀表达式的末尾。 - 第六个元素是减号,是运算符,将其压入栈中。 - 第七个元素是数字7,是操作数,将其添加到后缀表达式的末尾。 - 第八个元素是数字4,是操作数,将其添加到后缀表达式的末尾。 - 第九个元素是除号,是运算符,将其压入栈中。 - 第十个元素是数字8,是操作数,将其添加到后缀表达式的末尾。 - 第十一个元素是数字2,是操作数,将其添加到后缀表达式的末尾。 - 扫描完整个中缀表达式后,栈中还有运算符,将其依次弹出并添加到后缀表达式中,得到后缀表达式 6 3 * 7 4 - + 8 2 / -。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 43
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

玄澈_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值