zoukankan      html  css  js  c++  java
  • 数据结构——中缀转后缀表达式

    一、手工方式

    如果只是用于解题的话,这种方法是最快最准确的。但是它不适用于计算机。下面以a+b*c+(d*e+f)*g为例子讲以下人应该怎么把中缀表达式转换成后缀表达式。

    1. 按先加减后乘除的原则给表达式加括号

      结果:((a+(b*c))+(((d*e)+f)*g))

    2. 由内到外把每个括号里的表达式换成后缀

      最终结果:abc*+de*f+g*+

    这样就得到了中缀表达式转后缀表达式的最终结果。此法应付考试有神效。

    二、栈的方式

    计算机毕竟没有人的思路,需要借助栈来实现从中缀表达式到后缀表达式的转换。

    这里明确一下使用栈转换的算法思想

    从左到右开始扫描中缀表达式
    遇到数字, 直接输出
    遇到运算符
    a.若为“(” 直接入栈
    b.若为“)” 将符号栈中的元素依次出栈并输出, 直到 “(“, “(“只出栈, 不输出
    c.若为其他符号, 将符号栈中的元素依次出栈并输出, 直到遇到比当前符号优先级更低的符号或者”(“。 将当前符号入栈。
    扫描完后, 将栈中剩余符号依次输出

    下面以a+b*c+(d*e+f)*g为例子来讲讲计算机的转换过程。下面在描述栈的情况是直接用文字描述了,由左到右为栈底到栈顶表示栈空

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

      此时输出为:a

      栈的情况为:空

    2. 继续遍历,遇到+,将其放入栈中。

      此时输出为:a

      栈的情况为:+

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

      此时输出为:ab

      栈的情况为:+

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

      此时输出为:ab

      栈的情况为:+*

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

      此时输出为:abc

      栈的情况为:+*

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

      此时输出为:abc*+

      栈的情况为:+

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

      此时输出为:abc*+

      栈的情况为:+(

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

      此时输出为:abc*+d

      栈的情况为:+(

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

      此时输出为:abc*+d

      栈的情况为:+(*

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

      此时输出为:abc*+de

      栈的情况为:+(*

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

      此时输出为:abc*+de*

      栈的情况为:+(+

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

      此时输出为:abc*+de*f

      栈的情况为:+(+

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

      此时输出为:abc*+de*f+

      栈的情况为:+

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

      此时输出为:abc*+de*f+

      栈的情况为:+*

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

      此时输出为:abc*+de*f+g

      栈的情况为:+*

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

      此时输出为:abc*+de*f+g*+

      栈的情况为:空

    至此,中缀表达式转后缀已经全部完成,结果为abc*+de*f+g*+

    三、代码实现

     借助C++的stack实现

    //中缀表达式转后缀
    
    #include<iostream>
    #include<string>
    #include<stack>
    
    using namespace std;
    
    int prio(char op)                   //给运算符优先级排序
    {
        int priority;
        if (op == '*' || op == '/')
            priority = 2;
        if (op == '+' || op == '-')
            priority = 1;
        if (op == '(')
            priority = 0;
        return priority;
    }
    bool Trans(string &str,string &str1)     //引用传递
    {
        stack<char> s;                   //定义一个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 (prio(str[i]) <= prio(s.top()))   //栈顶优先级大于等于当前运算符,则输出
                    {
                        str1+= s.top();
                        s.pop();
                        if (s.empty())      //栈为空,停止
                            break;
                    }
                    s.push(str[i]);   //把当前运算符入栈
                }
            }
        }
        while (!s.empty())        //最后,如果栈不空,则弹出所有元素并输出
        {
            str1+= s.top();
            s.pop();
        }
        return true;
    }
    int main()                  //主程序
    {
        string infix;
        string postfix;
        cout << "请输入中缀表达式:" << infix << endl;
        cin >> infix;
        Trans(infix,postfix);
        cout << "后缀表达式为:" << postfix << endl;
        return 1;
    }

     测试通过!

    四、考研例题

    这里给出两道统考真题。

  • 相关阅读:
    JMeter性能测试中控制业务比例
    软件版本命名规范
    软件测试方法——静态测试与动态测试
    安装BugFree 3.0.4时出现的问题
    Linux下给mysql创建用户分配权限
    LoadRunner 测试脚本
    linux dd命令详解
    Linux查看CPU和内存使用情况
    Error:java: 无效的源发行版: 10
    rf接口自动化之结果校验
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/12864789.html
Copyright © 2011-2022 走看看