中缀表达式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了中缀表达式相关的知识,希望对你有一定的参考价值。

        表达式求值,属于数据结构——的典型应用。使用后缀表达式的与原因,是因为在求值的过程中,不需要考虑操作符的优先级。(结合性仍需要考虑)

        但是一般的书上只讲到如何处理二元操作符,并且结合性都是从左到右结合的。这里的实现能够处理一元操作符,并且能够处理从右向左结合的幂乘‘^‘操作符。

功能需求

        给定一个中缀表达式,求出该表达式的值。 
        要求支持“加减乘除 + - * /、取余 %、幂运算 ^、一元正负号 + -、括号 ()、数的科学表示法符号 E e”,其中含有一元操作符‘+ -‘,也含有从右向左结合性的操作符‘^‘,注意操作数的位数可以为多位。

分析

        需要考虑三个方面:① 优先级; ② 结合性; ③ 几元操作符;

        优先级:若操作符的优先级不同,那么先计算优先级高的。

        结合性:若操作符的优先级相同,那么先计算优先级的结合性决定求值顺序。

        几元操作符:一元和二元操作符,决定了参与求值的操作数的个数。

处理方法

        1. 利用数字0,将一元操作转化为二元操作,例如将"-3"转化为"0-3";

        2. 将操作符按照优先级分类,确定各个操作符的优先级;

        3. 结合性不同的操作符,由于数量较少(这里只有‘^‘),处理时单独判断;

具体步骤

        1. 判断是否有不匹配的括号

        2. 预处理中缀表达式 
                2.1 判断是否有不能处理的字符; 
                2.2 去除所有的空格; 
                2.3 处理一元操作符‘+‘和‘-‘: 
                        2.3.1 如果是在开始位置,在开始处添加"0"; 
                        2.3.2 如果是在“非数字字符”(右括号‘)’除外)之后,那么先在一元操作符前插入"(0",然后在一个“完整的数字”或者“括号后面”添加右括号")";

        3. 中缀转化为后缀表达式 (利用“操作符栈”) 
            遍历中缀表达式: 
                3.1 如果是操作数,读取其所有的位,然后进入后缀表达式队列; 
                3.2 如果是操作符( + – * / ^ % ) 
                        3.2.1 如果“操作符栈”为空,直接入栈; 
                        3.2.2 如果当前操作符优先级>栈顶元素优先级,那么入栈; 
                        3.2.3 如果当前操作符优先级<栈顶元素优先级,那么栈顶操作符出栈,循环执行; 
                        3.2.4 如果当前操作符优先级=栈顶元素优先级,如果当前元素是右结合性,那么入栈;否则,栈顶元素出栈;循环执行。 
                3.3 如果是左括号‘(‘,直接入栈 
                3.4 如果是右括号‘)‘,如果栈非空,那么栈顶元素出栈,直到遇到左括号‘(‘; 
                3.5 遍历结束中,将操作符栈中的元素依次出栈,添加到后缀表达式队列中。 
        4. 计算后缀表达式 
            从后缀表达式队列中依次取出元素 
                4.1 如果是操作数,那么将其压入“结果栈”中; 
                4.2 如果是操作符,从“结果栈”中取出两个元素,进行计算。(注意从栈中取元素的顺序和操作数的顺序是相反的) 
                遍历后缀表达式结束后,“结果栈”中的元素就是最终的结果。

 

//中缀表达式:需建两个栈——一个存数另一个存运算符 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
using namespace std;
int number[101],i=0,p=1;
char symbol[101],s[256],t[256];
void push()
{
    symbol[++p]=s[i];
}
void pop()
{
     switch(symbol[p--])
     {
         case+:number[p]+=number[p+1];break;
         case-:number[p]-=number[p+1];break;
         case*:number[p]*=number[p+1];break;
         case/:number[p]/=number[p+1];break;
     }
}
bool can()
{
    if((s[i])==+||s[i]==-&&symbol[p]!=() return 1;
    if((s[i]==*||s[i]==/)&&(symbol[p]==*||symbol[p]==/) ) return 1;
    return 0;//进行优先级处理    
}
int main()
{
     printf("string:");
     gets(s);
     s[strlen(s)]=);
     symbol[p]=(;
     while(i<strlen(s))
     {
         while(s[i]==()
         {
             push();
             i++;
         }
         int x=0;
         while(s[i]>=0&&s[i]<=9)
           x=x*10+s[i++]-0;
        number[p]=x;
        do
        {
            if(s[i]==))
            {
                while(symbol[p]!=() pop();
                number[--p]=number[p+1];
            }
            else
            {
                while(can()) pop();
                push();
            }
            i++;
        }
        while(i<strlen(s)&&s[i-1]==));
      } 
    printf("Result=%d,%d",number[0]);
    return 0;
}

 

以上是关于中缀表达式的主要内容,如果未能解决你的问题,请参考以下文章

中缀表达式

中缀表达式

中缀表达式转后缀表达式(Java代码实现)

中缀表达式求值的思路分析与代码实现

中缀表达式求值的思路分析与代码实现

栈实现综合计算器(中缀表达式),前缀,中缀,后缀表达式,逆波兰计算器