中缀表达式求值--数据结构(栈)

数据结构中一个重要内容就是中缀表达式求值,我们平常用的都是中缀表达式 如:2*(1+3)-4 、1+(3+2)*2 等等。之所以我们能快速得出答案,是因为我们知道计算的法则:从左往右,先乘除,后加减,括号最先计算。然而计算机并不懂这些,想要写段代码来让计算机也能计算,我们就必须先了解前缀,后缀表达式,以下是相关介绍及转换方法:
先来看两个例子

中缀表达式
2 *(1+3)- 4 、 9 /(1+2)+2 * (1+4)
前缀表达式
- * 2 + 1 3 4 、 + / 9 + 1 2 * 2 + 1 4
后缀表达式
2 1 3 + * 4 - 、 9 1 2 + / 2 1 4+ * +

看不懂没关系,现在来讲如何转换
(用上面例子的第二个进行讲解,懂得方法多练习即可)
中缀转前缀:

先将我们熟悉的中缀表达式 按照运算优先级关系 用括号括起来
(( 9 /(1+2))+(2 *(1 + 4)))
可以就看到,每个运算符都至少被一个运算符括着;
将每个运算符提到括着它的并且离它最近的括号前面;
提一个运算符,去一个括号;
初学者建议 从外往内,从左至右 ,下面是步骤:
1) +(9 /(1+2)) (2 *(1+4))
2) + / 9(1 +2 ) * 2(1+4)
3) + / 9 +1 2 * 2 +1 4
慢慢体会,之后稍加练习就能很熟练了

中缀转后缀

与转换前缀一样,先将我们熟悉的中缀表达式 按照运算优先级关系 用括号括起来
(( 9 /(1+2))+(2 (1 + 4)))
可以就看到,每个运算符都至少被一个运算符括着;
将每个运算符提到括着它的并且离它最近的括号后面;
提一个运算符,去一个括号;(还是从外往内,从左往右)
1)(9 / ( 1 + 2)) (2 * (1 +4 )+
2)9 (1 +2)/ 2 ( 1 + 4)
+
3)9 1 2 + / 2 1 4 + * +

现在给几个练习
(1+3)*5 / 2 -(1+3) *2
前缀表达式 :- / * +1 3 5 2 * + 1 3 2
后缀表达式:1 3 + 5 * 2 / 1 3 + 2 * -

慢慢练习,之后就能像求中缀表达式一样得心应手了

学习了前缀表达式和后缀表达式的转换,接下来就来看看如何利用前缀表达式和后缀表达式求中缀表达式吧
以练习题为例

前缀表达式 :- / * +1 3 5 2 * + 1 3 2
1)从后往前遍历 表达式
2)遇到数字就入栈,遇到运算符就让两个元素出栈,
3)记 a=第一个出栈数,b 第二个·出栈数 ,则 c =a 运算符 b,再将 c 入栈,接着遍历下一个元素
4)遍历完后,栈只剩最后一个元素(栈顶元素)即为最终结果

后缀表达式:从前往后遍历表达式(与前缀表达式大同小异,不细讲,下面提供代码)
利用计算机求中缀表达式一般是利用后缀表达式(边转换,边求值)代码如下:

#include<iostream>
#include<stack>
#include<string>
using namespace std;
int oper(char a,int b,int c)     //运算函数
{
    switch(a)
    {
        case '+' : return  (b + c); break;
        case '-' : return  (b - c); break;
        case '*' : return  (b * c); break;
        case '/' : return  (b / c); break;
    }
}
int main()
{
    stack<int>d;   	//存放数据栈
    stack<char>c;	//存放运算符栈
    int a,b;
    char s;		//a,b,s 作运算函数的参数
    string str;
    cin>>str;	//输入中缀表达式
    for(int i=0;i<str.size();i++)
    {
        if(str[i]=='+'||str[i]=='-')
        {
            if(c.empty()) c.push(str[i]); 	//运算符为空栈时,直接入栈
            else {
                while(!c.empty()&&(c.top()=='+'||c.top()=='-'||c.top()=='*'||c.top()=='/')) 	//运算优先级大于等于‘+’‘-’
                {
                    a=d.top();d.pop();
                    b=d.top();d.pop();
                    s=c.top();c.pop();
                    d.push(oper(s,b,a));
                }
                c.push(str[i]);	//运算结束将str[i]入栈
            }
        }
        else if(str[i]=='*'||str[i]=='/')
        {
            if(c.empty()||c.top()=='+'||c.top()=='-') c.push(str[i]);		//运算符栈为空,栈顶为‘+’‘-’时,直接入栈
            else{
                while(c.top()=='*'||c.top()=='/')
                {
                    a=d.top();d.pop();
                    b=d.top();d.pop();
                    s=c.top();c.pop();
                    d.push(oper(s,b,a));
                }
                c.push(str[i]);
            }
        }
        else if(str[i]=='(')  c.push(str[i]);
        else if(str[i]==')')
        {
            while(c.top()!='(')
            {
                a=d.top(); d.pop();
                b=d.top(); d.pop();
                s=c.top(); c.pop();
                d.push(oper(s,b,a));
            }
            c.pop();  	//  '('出栈
        }
        else
            d.push(str[i]-'0');
    }
    while(!c.empty())
    {
        a=d.top(); d.pop();
        b=d.top(); d.pop();
        s=c.top(); c.pop();
        d.push(oper(s,b,a));
    }
    cout<<d.top();
    return 0;
}

学习前缀、后缀表达式的一个目的就是想利用计算机求解中缀表达式
以上代码牵扯运算符优先级,如不能理解,建议 去mooc 慕课 找浙江大学 陈越、何钦铭老师的 数据结构 课程,里面有更详细的介绍。

  • 7
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值