【数据结构】中缀表达式求值解法


简述中缀表达式的做题思想:

例如:输入一个表达式为(3+2*5)-3*(1+3)/4-2

定义两个栈,一个是操作符栈(sdoc),一个是操作数栈(sdop)

1.首先判断输入的字符是数还是操作符

如果是操作数:

char cinch;int x;

while((cinch=getchar())!=' \n ') //此处是输入函数并且不为回车时继续输入字符

while ((c=getchar())!='\n') 
其中c=getchar()是输入一个字符,赋值给变量c, while ((c=getchar())!='\n') 就是当输入的字符c不是回车的时候,一直循环。


判断一个字符串是否是数字用isdigit函数 头文件是#include<cctype>,可以判断操作符是否为0-9之间的数字

if  isdigit(cinch)

然后这里涉及到一个cin.putback函数来做当输入数字是1位数以上的数字

if(isdigit(cinch)) 
		{
			cin.putback(cinch);
			cin>>x;
			sopd.push(x);
		}
cin.putback的解释用法是:

cin.putback(c)是将字符c放回到输入流中,这样后面用cin>>n时可以读完整的数字。
例如,输入为56 10 +时。
循环中第一次先读入一个字符c="5",
由于它是数字(isdigit),所以需要先putback,再用cin>>n读,这样n=56。如果不使用putback,由于5已经被读过了,下面从第二个字符读起,那么n=6,这样就错了。

2.如果是操作符的情况下分情况讨论

(1)如果输入的操作符是‘(’ 就直接入操作符栈

(2)如果输入的操作符的优先级大于当前栈顶元素,则执行运算

运算的执行是将栈顶操作符出栈,将操作数栈的栈顶元素出栈,再将栈顶元素出栈,stop.top2  stoc.top stop.top1

将计算出的结果再入栈。

(3)如果输入的操作符是‘)’则依次执行运算,直到栈顶元素为‘(’,停止运算,将操作符栈顶元素‘(’出栈


例子中:(3+2*5)-3*(1+3)/4-2

执行以上运算

先将‘#’入栈

(  入操作符栈

3入数字栈

+的优先级大于(,直接入操作符栈

2入数字栈

*的优先级大于+,直接入操作符栈

5入数字栈

发现)操作符,则执行运算操作,2*5=10,2,5出数字栈,10入数字栈,*出操作符栈,3+10=13,3,10出数字栈,13入数字栈,+出操作符栈,发现(操作符,结束运算,将(操作符出栈。此时数字栈内有13,操作符栈内有#

-的优先级大于#,直接入操作符栈

3入数字栈

*入操作符栈

发现(操作符,直接入操作符栈

1入数字栈

+大于(,直接入操作符栈

3入数字栈

发现)操作符,执行运算操作,3,1出栈,+出栈,3+1=4,4入数字栈,发下)。。

然后处理剩下的操作符,按照运算,依次运算到栈顶元素是‘#’,停止运算

以此类推,直到输入完毕,则输出数字栈栈顶元素。


自己编写的代码如下:

#include<iostream>
#include<cctype>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<stack>
using namespace std;

stack <int> sdop;
stack <char> sdoc;

int compare(char c) //优先级比较
{
	switch(c)
	{
		case '#':return 0;
		case '(':return 1;
		case '+':
		case '-':return 2;
		case '*':
		case '/':return 3;
	}
} 
void compute() //做运算
{
	int x=sdop.top();sdop.pop();
	int y=sdop.top();sdop.pop();
	char n=sdoc.top();sdoc.pop();
	int z;
	switch(n)
	{
		case '+':z=y+x;break;
		case '-':z=y-x;break;
		case '*':z=y*x;break;
		case '/':z=y/x;break;
		default:break;
	}
	sdop.push(z);
} 
int main()
{
    int n; 
	cin>>n;
	getchar();//接走回车 
	while(n--)
	{
		sdoc.push('#');
		char cinch,topch;
		int x;
		while((cinch=getchar())!='\n') //一直输入字符cinch 直到它是回车
		{
			//判断是操作数 
			if(isdigit(cinch))
			{
				cin.putback(cinch);//返回上一个看看是不是还是数字
				cin>>x;
				sdop.push(x); 
			}
			//判断是操作符
			else if(cinch=='(') sdoc.push(cinch);
			else if(cinch==')')
			{
				topch=sdoc.top();
				while(topch!='(')
				{
					compute();
					topch=sdoc.top();
				}
				sdoc.pop();
			} 
			else
			{
				topch=sdoc.top();
				while(compare(topch)>=compare(cinch))
				{
					compute();
					topch=sdoc.top();
				}
				sdoc.push(cinch);
			}
		} 
		topch=sdoc.top();
		while(topch!='#')
		{
			compute();
			topch=sdoc.top();
		}
		cout<<sdop.top()<<endl;
		while(!sdop.empty())
        sdop.pop();
        while(!sdoc.empty())
        sdoc.pop();
	}
	
	return 0;
}


猜你喜欢

转载自blog.csdn.net/IGGIRing/article/details/72870891