你还在为中缀表达式转后缀表达式而烦恼吗?

一文解决中缀转后缀

写在前面:

最近在复习数据结构的一些源码,虽然数据结构学完了,但是我觉得我还是得加强一下,关于代码的理解,不然面试或者考研就完蛋了,,,qwq,

你还在为中缀表达式转后缀表达式而烦恼吗?_第1张图片

  • 人的思路

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

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

结果:((a+(bc))+(((de)+f)*g))

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

最终结果:abc*+def+g+

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

  • 计算机的思路

毕竟计算机跟人不一样,它“笨”啊!人的思路它用不了。那么它该怎么把中缀表达式转换成后缀表达式呢?

计算机的思路需要用到栈,先来明确中缀表达式转后缀表达式的规则:

1)如果遇到操作数,我们就直接将其输出。

2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。

4)如果遇到任何其他的操作符,如**(“+”, “*”,“(”)**等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) “的情况下我们才弹出” ( “,其他情况我们都不会弹出” ( "。

5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

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

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

此时输出为:a

栈的情况为:空

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

此时输出为:a

栈的情况为:+

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

此时输出为:ab

栈的情况为:+

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

此时输出为:ab

栈的情况为:+*

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

此时输出为:abc

栈的情况为:+*

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

此时输出为:abc*+

栈的情况为:+

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

此时输出为:abc*+

栈的情况为:+(

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

此时输出为:abc*+d

栈的情况为:+(

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

此时输出为:abc*+d

栈的情况为:+(*

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

此时输出为:abc*+de

栈的情况为:+(*

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

此时输出为:abc*+de*

栈的情况为:+(+

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

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

栈的情况为:+(+

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

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

栈的情况为:+

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

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

栈的情况为:+*

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

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

栈的情况为:+*

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

此时输出为:abc*+def+g+

栈的情况为:空

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

代码实现
源代码
代码是用C++写的,不过还是用的面向过程的思路。代码如下:

#include 
#include 
#include 

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)        //   C++取引用str接受中缀表达式,str1存储后缀表达式
{
    stack<char> s;                          //   s存储运算符的优先级
    int i;
    for(i=0;i<str.size();i++)
    {
        if(str[i]>='0'&&str[i]<='9')
        {
            str1+=str[i];
            if(str[i+1]<'0'||str[i+1]>'9')      //    把数字和字符分开
            str1+=' ';
        }
        else
        {
            if(s.empty())                    //   s为空,直接压栈
            s.push(str[i]);
            else if(str[i]=='(')             //   str[i]=='(',直接压栈
            s.push(str[i]);
            else if(str[i]==')')             //    str[i]==')',一直出栈,直至遇见(,再把(弹出来
            {
                while(s.top()!='(')
                {
                    str1+=s.top();
                    s.pop();
                }
                s.pop();
            }
            else
            {
                while(prio(str[i])<=prio(s.top()))     //    当栈顶元素的优先级比str[i]大,直接出栈
                {
                    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;
    postfix.clear();
    cout<<"Please enter infix expression : "<<endl;
    while(cin>>infix)
    {
        Trans(infix,postfix);
        cout<<"The suffix expression is : "<<postfix<<endl;
        infix.clear();
        postfix.clear();
    }
    return 0;
}

你可能感兴趣的:(数据结构)