中缀表达式
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; }
以上是关于中缀表达式的主要内容,如果未能解决你的问题,请参考以下文章