【模板题】【栈】表达式求值问题总结:6263:布尔表达式,01:简单算术表达式求值,4132:四则运算表达式求值(终极BOSS)

6263:布尔表达式:输入一个布尔表达式,请你输出它的真假值

样例输入:
( V | V ) & F & ( F| V)
!V | V & V & !F & (F | V ) & (!F | F | !V & V)

(F&F|V|!V&!F&!(F|F&V))

思路:本题的关键就是定义优先级,表中含义是后来的符号是小于、等于、或者大于先前的符号。其中若符号相同先入的普遍大于后入的。对于“(”和“)”必须仔细考虑。如栈有"("则之后的符号都大,必须压入栈。目前读到“(”则此时它比任何符号都要小,直接入栈。目前读到“)”它优先级最大,必须把能计算的计算完,直到遇到“=”。可以这么考虑:即目前读入的需要压入栈的则优先级小。在栈中要一直保持优先级高的在上面。其中“0”代表非法的比较,或者说表达式中不存在这种情况。
先\后 |  &  !  (  )  #
 |       > < < < > >
 &     > > < < > >
 !       > > = < > >
 (      < < < < = 0
 )      > > > 0 > >

 #     < < < < 0 =

注意:
1、此题的两个“!”之间是=的优先级,即相互抵消
2、注意若出现>则需要循环计算到!=>为止

3、bool型不能用~取反,只能用1-n[ntop-1]

#include<cstdio>
#include<iostream>
#include<string>
#include<map>
using namespace std;
map<char,int>index;//| &   !   (   )   #
char pri[7][7]={ {'>','<','<','<','>','>'},//|
				 {'>','>','<','<','>','>'},//&
				 {'>','>','=','<','>','>'},//!
				 {'<','<','<','<','=','0'},//(
				 {'>','>','>','0','>','>'},//)
				 {'<','<','<','<','0','='}};//#
char get(char a,char b)
{
	int ida=index[a],idb=index[b];
	return pri[ida][idb];
}
void solve(string s)
{
	bool n[100];
	char o[100],x,op;
	int ntop=0,otop=0;
	int i=0;
	o[otop++]='#';//添加#
	for (i=0;i<s.length();i++)
	{
		if (s[i]=='V')	n[ntop++]=1;
		else if (s[i]=='F') n[ntop++]=0;
		else //op
		{
			x=get(o[otop-1],s[i]);
			while(x=='>')
			{
				op=o[otop-1];otop--;
				switch (op)
				{
					case '|': n[ntop-2]=n[ntop-2]|n[ntop-1];ntop--;break;
					case '&': n[ntop-2]=n[ntop-2]&n[ntop-1];ntop--;break;
					case '!': n[ntop-1]=1-n[ntop-1];break;
				}
				x=get(o[otop-1],s[i]);
			}
			if (x=='=')
				otop--;
			else if (x=='<')
				o[otop++]=s[i];
		}
	}
	if (n[0]==1)cout<<"V"<<endl;
	else cout<<"F"<<endl;
}

int main()
{
	index['|']=0;index['&']=1;index['!']=2;index['(']=3;index[')']=4;index['#']=5;//初始化索引
	int i;
	string s,temp;
	while(getline(cin,s))
	{
		i=0;temp="";//注意temp清空
		while(i<s.length())//除空格
		{
			while(s[i]==' ')i++;
			temp+=s[i]; i++;
		}
		temp+="#";//表达式结束
		solve(temp);
	}
	return 0;
}

01:简单算术表达式求值——计算变为数字

#include<iostream>
#include<map>
#include<string>
using namespace std; //+   -   *   /   %   #
char pri[6][6]={/*+*/{'>','>','<','<','<','>'},
				/*-*/{'>','>','<','<','<','>'},
				/***/{'>','>','>','>','>','>'},
				/*/*/{'>','>','>','>','>','>'},
				/*%*/{'>','>','>','>','>','>'},
				/*#*/{'<','<','<','<','<','='}};
map<char,int>index;
char getpri(char a,char b)
{ 
	int ida=index[a],idb=index[b];
	return pri[ida][idb];
}
int main()
{
	int i;
	string s,temp="";
	char o[100],x,op;
	int n[100],ntop=0,otop=0,t;
	index['+']=0;index['-']=1;index['*']=2;index['/']=3;index['%']=4;index['#']=5;
	getline(cin,s);
	i=0;
	while(i<s.length())
	{
		while(s[i]==' ')i++;
		temp+=s[i];i++;
	}
	s=temp+"#";t=0;
	o[otop++]='#';
	for (i=0;i<s.length();i++)
	{
		if (isdigit(s[i]))
			t=t*10+s[i]-'0';
		else 
		{
			n[ntop++]=t;t=0;
			x=getpri(o[otop-1],s[i]);
			while(x=='>')
			{
				op=o[otop-1];otop--;
				switch (op)
				{
					case'+':n[ntop-2]=n[ntop-2]+n[ntop-1];ntop--;break;
					case'-':n[ntop-2]=n[ntop-2]-n[ntop-1];ntop--;break;
					case'*':n[ntop-2]=n[ntop-2]*n[ntop-1];ntop--;break;
					case'/':n[ntop-2]=n[ntop-2]/n[ntop-1];ntop--;break;
					case'%':n[ntop-2]=n[ntop-2]%n[ntop-1];ntop--;break;
				}
				x=getpri(o[otop-1],s[i]);
			}
			if (x=='=') otop--;
			else if (x=='<') o[otop++]=s[i];
		}
	}
	cout<<n[0]<<endl;
	return 0;
}

【终极综合运用】:4132:四则运算表达式求值:包含括号、数字、小数点

注意很多函数要包含头文件
<iomanip>  setiosflags(ios::fixed)<<setprecision(2)
<ctype.h>  isdight()
<cmath>    pow()

#include<iostream>
#include<map>
#include<string>
#include<ctype.h>
#include<cmath>
#include<iomanip>
using namespace std;//    +   -   *   /   (   )   #
char pri[7][7]={/* + */ {'>','>','<','<','<','>','>'},
				/* - */ {'>','>','<','<','<','>','>'},
				/* * */ {'>','>','>','>','<','>','>'},
				/* / */ {'>','>','>','>','<','>','>'},
				/* ( */ {'<','<','<','<','<','=','0'},
				/* ) */ {'>','>','>','>','0','>','>'},
				/* # */ {'<','<','<','<','<','0','='}};
map<char,int>index;
double n[100];
char getpri(char a,char b)
{
	int x=index[a],y=index[b];
	return pri[x][y];
}
int main()
{
	index['+']=0;index['-']=1;index['*']=2;index['/']=3;index['(']=4;index[')']=5;index['#']=6;
	char o[100],x,op;
	int ntop=0,otop=0,i,len=0;
	double n1=0,n2=0;
	bool xiaoshu=false,isnumber=false;
	string s;
	getline(cin,s);
	s=s+"#";
	o[otop++]='#';
	for (i=0;i<s.length();i++)
	{
		if (isdigit(s[i]))
		{
			isnumber=true;
			if (xiaoshu)
			{
				n2=n2*10+s[i]-'0';
				len++;
			}
			else n1=n1*10+s[i]-'0';
		}
		else if (s[i]=='.')	xiaoshu=true;
		else//op 
		{
			if (isnumber)//防止出现两个符号连续的情况
				n[ntop++]=n1+(float)pow(10,0-len)*n2;//数字入栈
			xiaoshu=false;isnumber=false;len=0;n1=0;n2=0;//初始化
			x=getpri(o[otop-1],s[i]);//获取优先级
			while(x=='>')
			{
				op=o[otop-1];otop--;
				switch (op)
				{
					case '+':n[ntop-2]=n[ntop-2]+n[ntop-1];ntop--;break;
					case '-':n[ntop-2]=n[ntop-2]-n[ntop-1];ntop--;break;
					case '*':n[ntop-2]=n[ntop-2]*n[ntop-1];ntop--;break;
					case '/':n[ntop-2]=n[ntop-2]/n[ntop-1];ntop--;break;
				}
				x=getpri(o[otop-1],s[i]);
			}
			if (x=='=') otop--;
			else if (x=='<') o[otop++]=s[i];
		}
	}
	cout<<setiosflags(ios::fixed)<<setprecision(2)<<n[0]<<endl;
	return 0;
}

心得:表达式求值真的是掌握方法就很简单,第一道题花了很久,主要是有关算法都不记得了,重新温故,才慢慢理清思路。最重要的就是找好优先级。其他的都很简单,注意细节就好。

猜你喜欢

转载自blog.csdn.net/always_ease/article/details/80714854