【数据结构】栈的运用(一)无括号表达式求值

无符号表达式求值

  • 利用栈的特性进行表达式计算。
  • 主要思路是做一个数字栈和一个符号栈,分别存放数字和运算符。
  • 利用入栈的运算符和栈内运算符相比较优先级达到计算目的。

代码收获

  • atoi字符串转数字功能在devc++上调试时结果正确,运行时结果错误。经研究发现,这个函数在转字符时候会在运行的情况里把转的字符末尾加0,而调试的时候不会。比如转字符‘5’,atoi就会转成50,从而影响最后结果。后发现atoi是转字符串,字符串是字符数组最后需要带尾零,可能是由于字符不是字符串导致的问题。
  • 入栈运算符的优先级如果是同级,也需要进行栈内数字运算。
  • 此代码只能进行个位数的无符号表达式求值,思考后发现,将输入的值做成队列,然后可以算得数字位数,从而进行多位数的表达式求值。

栈的归档

栈的存储结构(一)顺序栈
栈的存储结构(二)双端栈
栈的存储结构(三)链栈
栈的运用(一)无括号表达式求值
栈的运用(二)无括号表达式求值修正版

# include <stdio.h>
# include <stdlib.h>
#define MAXSIZE 100 
typedef struct stack{
	int top;
	int ele[MAXSIZE]; 
}stacknum,*stacknump;
typedef struct stackop{
	int top;
	char ele[MAXSIZE];
}stackop,*stackopp;
//初始化 
void InitialStack(stacknump* ST,stackopp* OP){
	*ST=(stacknump)malloc(sizeof(stacknum));
	*OP=(stackopp)malloc(sizeof(stackop));
	(*ST)->top = -1;//栈顶指针为-1 说明是空栈,和顺序存储思想相似 
	(*OP)->top = -1;
}
char getops(stackopp OP){//获取操作栈顶元素并返回元素
	return OP->ele[OP->top];
}
int getint(char *a){//字符转换数字 
	return *a-'0';
}
int compareop(char a,stackopp OP){//比较优先级  $ (+-) (*/)  $是0 +-做1 乘除做2 如果第一个数减第二个数负数,则优先级比第二个数高,等于0表示相等,小于0表示优先级小 
	char b;
	b = getops(OP);
	int aa,bb;
	switch(a){
		case '$': {
			aa=0;
			break;
		}
		case '+':
		case '-':{
			aa=1;
			break;
		}
		case '*':
		case '/':{
			aa=2;
			break;
		}
	}
	switch(b){
		case '$': {
			bb=0;
			break;
		}
		case '+':
		case '-':{
			bb=1;
			break;
		}
		case '*':
		case '/':{
			bb=2;
			break;
		}
	}
	if(aa-bb>0){//1代表要入栈的比栈顶优先级高,0代表相等,-1代表小于 
		return 1;
	}else if(aa-bb==0){
		return 0; 
	}else{
		return -1;
	}
}
int excuit(int num2,int num1,char ops){//运算 
	switch(ops){
		case '+':{
			return num2+num1;
		}
		case '-':{
			return num2-num1;
		}
		case '*':{
			return num2*num1;
		}
		case '/':{
			return num2/num1;
		}
	}
}
//入栈 
//看要进栈的优先级是否高于栈顶优先级
//比符号栈顶高进栈
//比符号栈顶低取出元素栈顶元素和元素栈顶下的元素
//取出符号栈顶的元素进行计算
//将结果进元素栈后继续比较将进栈符号的优先级,比栈顶符号高就进栈,低就继续走上述运算。 
int CauculateStack(stacknump ST,stackopp OP){
	printf("输入数字与运算符,$结束\n");
	OP->top++;
	OP->ele[OP->top]='$';//先将操作栈入$ 
	int flag = 1;
	while(flag){
		char c;
		c = getchar();
		if(c!='$'){
			switch(c){
				case '+':
				case '-':
				case '*':
				case '/':{
					//取出前面一个数对比将要入栈的优先级
					int flag2=1;
					while(flag2){
						int prime;
						prime = compareop(c,OP);
						if(prime>0){
							OP->top++;//操作符入栈 
							OP->ele[OP->top]=c;
							flag2=0;
						}else{//取出数字栈的2个数并且取出操作符中的一个数进行运算  再将运算结果入数字栈 
							int num1,num2;
							char ops;
							num1 =ST->ele[ST->top];
							ST->top--;
							num2 = ST->ele[ST->top];
							ST->top--;
							ops = getops(OP);
							OP->top--;
							int res;
							res = excuit(num2,num1,ops);
							ST->top++;
							ST->ele[ST->top]=res;
						}
					}
				break;
				}
				default:{//数字直接入栈 
					int numb;
					numb = getint(&c);
					ST->top++;
					ST->ele[ST->top]=numb;
					break;
				}
			} 			
		} else{
			flag = 0;
			//只要操作栈不为最初的那个$,就进行运算; 
			while(OP->top!=0){
				//出数字栈2个然后出运算栈1个 结果入栈 
				int num3,num4;
				char ops2;
				num3 =ST->ele[ST->top];
				ST->top--;
				num4 = ST->ele[ST->top];
				ST->top--;
				ops2 = getops(OP);
				OP->top--;
				int res2;
				res2= excuit(num4,num3,ops2);
				ST->top++;
				ST->ele[ST->top]=res2;
			} 
		} 
	}getchar();
	printf("结果为%d",ST->ele[0]);//打印结果为数字栈的第一个 
	return 0;
}

void main(){
	stackopp OP;
	stacknump ST;
	InitialStack(&ST,&OP);
	CauculateStack(ST,OP);
}

终端显示

输入数字与运算符,$结束
5*5-2+3*3+2-5*9$
结果为-11

猜你喜欢

转载自blog.csdn.net/yehuozhili/article/details/82950439
今日推荐