数据结构——中缀转后缀表达式

怎甘沉沦 提交于 2020-08-18 20:59:35

一、手工方式

如果只是用于解题的话,这种方法是最快最准确的。但是它不适用于计算机。下面以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;
}

 

 测试通过!

四、考研例题

这里给出两道统考真题。

 

 

 

 

 

 

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!