主要包括一些中缀、后缀表达式值的计算、表达式是否合法的判断

后缀表达式的讲解:

https://baike.sogou.com/v53851686.htm?fromTitle=%E5%90%8E%E7%BC%80%E8%A1%A8%E8%BE%BE%E5%BC%8F&ch=frombaikevr

人工怎么写出中缀表达式的后缀表达式

 计算机实现方法:

NOIP and CSP真题

2022 逻辑表达式

这个其实也是在讨论&和|的无用情况,但是要记录整个式子的无用计算次数,所以这里用stack和pair两种结构,自底向上统计无用情况

题解:https://www.cnblogs.com/shirlybaby/p/17803059.html

2020 表达式 http://ybt.ssoier.cn:8088/problem_show.php?pid=2006

 这个题要求的是每个元素对总体结果的改变情况,因为在&和|运算中,有的元素值的不同对总体结果没有影响,所以这道题的思路就是建立表达式树,

然后对树上每个元素打上标记,看是否是一个无用的,在打标机的过程的过程中用DFS,而且还要标记下传

题解:https://www.cnblogs.com/shirlybaby/p/17803737.html

 

1356:计算(calc)----中缀

表达式求值:这里的表达式就是最正常的表达式,有加减乘除,括号

第一种方法:直接计算,不用转为后缀表达式,边弄边算

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
using namespace std;
 //表达式求值,这里的表达式就是最正常的表达式,有加减乘除,括号等
//用一个函数来判断运算符的优先级
int n,m;
int lev(char x)//运算符优先级
{
    if(x=='+'||x=='-')//加减的优先级很低
        return 1;
    if(x=='*'||x=='/')
        return 2;
    if(x=='^')
        return 3;
    return 0;//括号的优先级很低
}
 
void calculate(stack<int> &s1,stack<char> &s2)//弹出栈顶元素并计算//参数是一个运算数的栈和一个运算符的栈
{
    /*取出后弹出栈*/
    int y=s1.top();
        s1.pop();
    int x=s1.top();
        s1.pop();//弹出两个操作数
    char z=s2.top();
        s2.pop();//弹出一个操作符
 
    /*根据运算符计算,并压入栈*/
    if(z=='+')
        s1.push(x+y);
    if(z=='-')
        s1.push(x-y);//这些也要注意是谁加谁是谁减谁 
    if(z=='*')
        s1.push(x*y);
    if(z=='/')
        s1.push(x/y);
    if(z=='^')
        s1.push(pow(x,y));//注意谁是底数,谁是指数 
}
 

char str[1000000];
 
int main(){
 
    scanf("%s",str+1);
    n=strlen(str+1);
 
 
    stack<int> s1;
    stack<char> s2;
    int temp=0;
    bool flag=false;//这两个参数都是用来临时保存temp和标记是否是数flag的 
    for(int i=1;i<=n;i++)
    {
        if('0'<=str[i]&&str[i]<='9')//判断当前字符是否为数字
        {
            temp=(temp<<3)+(temp<<1)+str[i]-'0';//temp*=10+str[i]-'0' 
            flag=true;
        }
        else
        {//操作数在这里入栈 
            if(flag)
            {
                s1.push(temp);
                temp=0;
                flag=false;//操作数入栈,数被temp临时保存,这里入栈后temp清零
            }
            if(str[i]=='(')
            {
                s2.push(str[i]);
                continue;
            }
            if(str[i]==')')
            {
                while(s2.top()!='(')//注意这里要判断前一个是不是(,有这种可能性
                    calculate(s1,s2);
                s2.pop();//注意这里还要弹栈,因为有一个( 
                continue;
            }
            while(!s2.empty()&&lev(s2.top())>=lev(str[i]))//优先级判断//运算符入栈
                calculate(s1,s2);//如果运算符栈不空而且当前的运算符优先级较低,就先算了来(即先计算优先级高的) 
            s2.push(str[i]);//运算符入栈
        }//这一这里面就是一个if-else,分为是否是操作符和是否是操作数 
    }
    if(flag)
    {
        s1.push(temp);
        temp=0;
        flag=false;
    }
    while(!s2.empty())
        calculate(s1,s2);
    cout<<s1.top()%10000<<endl;
    return 0;
}

 

1358:中缀表达式值(expr)

没有括号,但是需要判断是不是合法的中缀表达式,而且-可能是负数符号(但感觉好像没管??)

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#define Int stack<int>
#define Char stack<char>
using namespace std;
//这里的用法
Int s1;Char s2;
inline int lev(char x){
	if(x=='+'||x=='-') return 1;      //用到很多的内联函数,为了节省栈空间 
	if(x=='*'||x=='/') return 2;
	if(x=='^') return 3;
	return 0;//数字或括号返回0 
} 
//快速幂的迭代写法
inline int ksm(int s,int t){
	int ans=1;
	while(t){
		if(t&1) ans*=s;//如果t是奇数 
		s*=s;  //乘以本身,是转化为2进制的写法 
		t>>=1;//t除以2 
	}
	return ans;
} 
//弹栈并且计算 
inline  void js(Int &s1,Char &s2){
	int y=s1.top();s1.pop();
	int x=s1.top();s1.pop();//运算数 
	char c=s2.top();s2.pop();//运算符
	if(c=='-') s1.push(x-y);
	if(c=='+') s1.push(x+y);
	if(c=='*') s1.push(x*y);
	if(c=='/') s1.push(x/y);
	if(c=='^') s1.push(ksm(x,y));//快速幂 
}
inline int c(int x){
	return x!=0;//这个函数是用来判断表达式是否合法的,和判断优先级一起用的 
}
char sr[100001];
int sum[100001];



int main(){
	scanf("%s",sr+1);//注意写法,是从1开始的
	int n=strlen(sr+1)-1;//-1是因为去除末尾的@
	for(int i=1;i<=n;i++){
		sum[i]+=sum[i-1];
		if(sr[i]=='(') ++sum[i];
		if(sr[i]==')') --sum[i];     //这个for循环是用来匹配检查的,判断合法性,()是否匹配 
	} 
	bool out=0;//判断是否存在*/ 等情况
	for(int i=2;i<=n;i++){
		if(c(lev(sr[i]))&&c(lev(sr[i-1]))){
			out=1;
			break;
		}
	} 
	if(n==1&&c(lev(sr[1]))||sum[n]||out){
		cout<<"NO"<<endl;//不合法的三种情况 
		return 0;
	}
	//判断完了合法性后就和calc一样了,开始计算 
	Int s1;
	Char s2;
	int temp=0,flag=0;
	for(int i=1;i<=n;i++){
		if(sr[i]>='0'&&sr[i]<='9'){
			temp=(temp<<3)+(temp<<1)+sr[i]-'0';//注意前面的写法,等价于temp*10 
			flag=1;
		}
		else{
			if(flag) {
				s1.push(temp);
				temp=0;flag=0;
			}//先判断是不是数 
			if(sr[i]=='('){
				s2.push(sr[i]);
				continue;//推出本次循环 
			}
			if(sr[i]==')'){
				while(s2.top()!='(') js(s1,s2);
				s2.pop();//然后就弹栈
				continue;//退出本次循环 
			}
			while(!s2.empty()&&lev(sr[i])<=lev(s2.top())) js(s1,s2);
			s2.push(sr[i]);//运算符入栈 
			
		} 
	}
	if(flag){
		s1.push(temp);
		temp=flag=0;
	}
	while(!s2.empty()) js(s1,s2);
	cout<<s1.top();
	
	
return 0;
}

  

1331:【例1-2】后缀表达式的值

在一本通上面不行了,会出现编译错误,好像是gets函数的原因,不懂!!!!

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
using namespace std;
//栈
char s[256];
int stack[267];//注意stack类型是int,不放运算符 
void comp(char s[]){
	int top=0,i=0;
	int x=0; 
	while(i<=strlen(s)-2){//因为最后一个是@
	switch(s[i]){  //计算后缀表达式:要用到switch 
		case '+': stack[--top]+=stack[top+1];break;
		case '-': stack[--top]-=stack[top+1];break;
		case '*': stack[--top]*=stack[top+1];break;
		case '/': stack[--top]/=stack[top+1];break;
		default: x=0;while(s[i]!=' ') x=x*10+s[i++]-'0';//处理多位数 
		stack[++top]=x;break;
	} 
		i++;
	}//年纪大了:要注意switch的写法 
	cout<<stack[top]<<endl;
} 


int main(){
	gets(s);//要用gets() 
	comp(s);
    return 0;
}

1358:中缀表达式值(expr)

中缀表达式的值,还带检查表达式合不合法,注意表达式不合法的三种情况:

1)n==1且第一个是运算符

2)括号不匹配 

3)出现连续运算符 

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#define Int stack<int>
#define Char stack<char>
using namespace std;

//这道题既需要判断,也需要计算 
//这里的用法
Int s1;Char s2;
inline int lev(char x){
	if(x=='+'||x=='-') return 1;      //用到很多的内联函数,为了节省栈空间 
	if(x=='*'||x=='/') return 2;
	if(x=='^') return 3;
	return 0;//数字或括号返回0 
} 
//快速幂的迭代写法
inline int ksm(int s,int t){
	int ans=1;
	while(t){
		if(t&1) ans*=s;//如果t是奇数 
		s*=s;  //乘以本身,是转化为2进制的写法 
		t>>=1;//t除以2 
	}
	return ans;
} 
//弹栈并且计算 
inline  void js(Int &s1,Char &s2){
	int y=s1.top();s1.pop();
	int x=s1.top();s1.pop();//运算数 
	char c=s2.top();s2.pop();//运算符
	if(c=='-') s1.push(x-y);
	if(c=='+') s1.push(x+y);
	if(c=='*') s1.push(x*y);
	if(c=='/') s1.push(x/y);
	if(c=='^') s1.push(ksm(x,y));//快速幂 
}
inline int c(int x){
	return x!=0;//这个函数是用来判断表达式是否合法的,和判断优先级一起用的 
}
char sr[100001];
int sum[100001];



int main(){
	scanf("%s",sr+1);//注意写法,是从1开始的
	int n=strlen(sr+1)-1;//-1是因为去除末尾的@
	for(int i=1;i<=n;i++){
		sum[i]+=sum[i-1];
		if(sr[i]=='(') ++sum[i];
		if(sr[i]==')') --sum[i];     //这个for循环是用来匹配检查的,判断合法性,()是否匹配 
	} 
	bool out=0;//判断是否存在*/ 等情况
	for(int i=2;i<=n;i++){
		if(c(lev(sr[i]))&&c(lev(sr[i-1]))){
			out=1;
			break;
		}
	} 
	if(n==1&&c(lev(sr[1]))||sum[n]||out){
		cout<<"NO"<<endl;//不合法的三种情况 
		                //这个就很考验人了:1)n==1  2)第一个是运算符 3)括号不匹配  4)出现连续运算符 
		return 0;
	}
	//判断完了合法性后就和calc一样了,开始计算 
	Int s1;
	Char s2;
	int temp=0,flag=0;
	for(int i=1;i<=n;i++){
		if(sr[i]>='0'&&sr[i]<='9'){
			temp=(temp<<3)+(temp<<1)+sr[i]-'0';//注意前面的写法,等价于temp*10 
			flag=1;
		}
		else{
			if(flag) {
				s1.push(temp);
				temp=0;flag=0;
			}//先判断是不是数 
			if(sr[i]=='('){
				s2.push(sr[i]);
				continue;//推出本次循环 
			}
			if(sr[i]==')'){
				while(s2.top()!='(') js(s1,s2);
				s2.pop();//然后就弹栈
				continue;//退出本次循环 
			}
			while(!s2.empty()&&lev(sr[i])<=lev(s2.top())) js(s1,s2);
			s2.push(sr[i]);//运算符入栈 
			
		} 
	}
	if(flag){
		s1.push(temp);
		temp=flag=0;
	}
	while(!s2.empty()) js(s1,s2);
	cout<<s1.top();
	
	
return 0;
}

  

1353:表达式括号匹配(stack)

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

string s;
stack<char> ss;


int main(){
	cin>>s;
	for(int i=0;s[i]!='@';i++){
		if(s[i]=='(') ss.push(s[i]);
		if(s[i]==')'){
			if(!ss.empty()) ss.pop();
			else {
				cout<<"NO"<<endl;
				return 0;
			}
		}
		
	}
	if(!ss.empty()) cout<<"NO"<<endl;
	else cout<<"YES"<<endl;
return 0;
}

1354:括弧匹配检验

括弧匹配检验、字符串匹配问题:思想:用数字来表示字符,可以找到正确的规律

char str[10000];
stack<int> S;//用1代表(,2代表),3代表[,4代表]//用数字来代表符号 
int main(){
    cin>>str;
    int len=strlen(str);
    for(int i=0;i<len;i++)
    {
        if(str[i]=='(')//记录左圆括号
            S.push(1);
        else if(str[i]==')')//记录右圆括号
        {
            if(S.empty())//栈为空
                S.push(2);
            else if(S.top()==1)
                S.pop();
            else
                S.push(2);
        }
        else if(str[i]=='[')//记录左方括号
            S.push(3);
        else if(str[i]==']')//记录右方括号
        {
            if(S.empty())//栈为空
                S.push(4);
            else if(S.top()==3)
                S.pop();
            else
                S.push(4);
        }
    }
    if(S.empty())
        printf("OK");
    else
        printf("Wrong");
    return 0;
} 

  

1355:字符串匹配问题(strs)

int n;
char s[256]; 
int a[256];
char b[256]={0};
void change(char s[]){
	for(int i=0;i<strlen(s);i++){
		if(s[i]=='{') a[i+1]=1;
		if(s[i]=='[') a[i+1]=2;
		if(s[i]=='(') a[i+1]=3;
		if(s[i]=='<') a[i+1]=4;
		if(s[i]=='>') a[i+1]=5;
		if(s[i]==')') a[i+1]=6;
		if(s[i]==']') a[i+1]=7;
		if(s[i]=='}') a[i+1]=8;//将较多的符号转化为数字来判断,找规律:加起来等于9的是合理的 
	}
} 

int main(){
	cin>>n;
	while(n--){
		cin>>s;
		change(s);
		int t=0;
		for(int j=1;j<=strlen(s);j++){
			if(a[j]<=4)
			if(a[j]>=b[t]) b[++t]=a[j];
			else break;
			if(a[j]>=5)
			if(a[j]+b[t]==9) t--;
			else t++;
		}
		if(t==0) cout<<"YES"<<endl;//还是用栈中元素个数来判断正误 
		else cout<<"NO"<<endl;
	}
return 0;
}

1357:车厢调度(train)
就是模拟弹栈的时候进入的序列是否是合法的序列

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int n;
int a[1001];
int stack[1001];

int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	int top=0;//记住有这个标志啊 
	for(int i=1,cur=1;i<=n;i++){
		while(cur<=a[i]) stack[++top]=cur++;  //第一种情况,需要进栈 
		if(stack[top]==a[i]) --top;//若在栈顶则弹出(第二种情况,等于) 
		else {
			cout<<"NO"<<endl;//如果不在栈顶,就错误 (第三种情况) 
			return 0;
		}  
	}
	cout<<"YES"<<endl;
return 0;
}

  

 

 posted on 2020-02-05 17:38  shirlybabyyy  阅读(41)  评论(0编辑  收藏  举报