表达式求值

算法思想:

表达式求值是一个典型问题,这里用的是“算符优先法”,是栈应用的又一典型例子

使用两个工作栈,一个叫做OPTR栈,用以寄存运算符,另一个叫做OPND,用以寄存操作数或运算结果

算法基本思想:(1)首先置操作数栈为空栈,表达式起始符“#”为运算符栈的栈底元素

(2)依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权,栈顶元素的优先级大于等于当前元素的优先级,OPND弹出两个元素运算后进OPND栈,栈顶元素小于当前运算符优先级时候直接入OPTR栈,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为“#”)

Expression.h文件 

/************************************
	文件路径:3 栈和队列\Expression 
	文件名称及类型:Expression.h
	实现功能:表达式求值相关操作列表以及各种需要类型的定义 
	writing time: 2018.8.12
************************************/

#ifndef EXPRESSION_H
#define EXPRESSION_H

typedef char SElemType;
#include"..\SequenceStack\SequenceStack.cpp"

typedef SElemType OperandType;//操作数类型
typedef SElemType OperatorType;//运算符类型

//算数表达式求值的算符优先算法,设OPTR和OPND分别为运算符栈和操作数栈,OP为运算符集合
OperandType EvaluateExpression();

//获取操作符栈栈的栈顶元素
OperatorType GetTop_OPTR(SqStack S); 

//判断c是否属于操作符集
Status In(SElemType c);

//判断栈中操作符o1与表达式中的操作符o2的优先级
OperatorType Precede(OperatorType o1,OperatorType o2);

//计算表达式的值
OperandType Operate(OperandType a,OperatorType theta,OperandType b);

#endif

Expression.cpp文件 

/************************************
	文件路径:3 栈和队列\Expression 
	文件名称及类型:Expression.cpp
	实现功能:表达式求值相关操作实现
	writing time: 2018.8.12
************************************/

//#ifndef EXPRESSION_CPP 
//#define EXPRESSION_CPP

#include"Expression.h"

//算数表达式求值的算符优先算法,设OPTR和OPND分别为运算符栈和操作数栈,OP为运算符集合
OperandType EvaluateExpression(){
	SqStack OPND,OPTR;
	OperatorType x,theta;
	OperandType a,b,c;
	
	InitStack(OPTR); Push(OPTR,'#');
	InitStack(OPND); c=getchar();
	
	printf("%c\n",GetTop_OPTR(OPTR));
	//GetTop(OPTR,x);
	while(c!='#'||(GetTop_OPTR(OPTR))!='#'){
		if(!In(c)){//不是运算符则进操作数栈 
			Push(OPND,c);
			c=getchar();
		}
		else{
			//GetTop(OPTR,x);
			printf("GetTop_OPTR(OPTR)=%c c=%c\n",GetTop_OPTR(OPTR),c);
			switch(Precede(GetTop_OPTR(OPTR),c)){
				case'<':Push(OPTR,c);c=getchar();break;//栈顶元素优先级低 
				case'=':Pop(OPTR,x);c=getchar();break;//脱括号并接受下一个字符
				case'>':Pop(OPTR,theta);
				Pop(OPND,b);Pop(OPND,a);
				Push(OPND,Operate(a,theta,b)); break;
			}
			printf("运算符栈顶为%c\n",GetTop_OPTR(OPTR));
			printf("操作数栈顶为%d\n",GetTop_OPTR(OPND));
		}
	}
	Pop(OPND,x);
	return x;
}

//获取操作符栈栈的栈顶元素
OperatorType GetTop_OPTR(SqStack S){
	SElemType e;
	GetTop(S,e);
	return e;
}

//判断c是否属于操作符集
Status In(SElemType c){
	switch(c){
		case'+':
		case'-':
		case'*':
		case'/':
		case'(':
		case')':
		case'#':
			return TRUE;
		default:
			return FALSE;
	}
}

//判断栈中操作符o1与表达式中的操作符o2的优先级
OperatorType Precede(OperatorType o1,OperatorType o2){
	switch(o2){
		case'+':
		case'-':
			if(o1=='('||o1=='#')
				return '<';
			else
				return '>';
			break;
		case'*':
		case'/':
			if(o1=='*'||o1=='/'||o1==')')
				return '>';
			else
				return '<';
			break;
		case'(':
			if(o1==')'){
				printf("括号匹配错误!\n");
				exit(ERROR);
			}
			else
				return '<';
			break;
		case')':
			if(o1=='(')
				return '=';
			else if(o1=='#'){
				printf("表达式中缺少左括号!\n");
				exit(ERROR);
			}
			else
				return '>';
		case'#':
			if(o1=='#')
				return '=';
			else if(o1=='('){
				printf("表达式中缺少右括号!\n");
				exit(ERROR); 
			}
			else
				return '>';
	}
}

//计算表达式的值
OperandType Operate(OperandType a,OperatorType theta,OperandType b){
	switch(theta){
		case'+':return (a-'0')+(b-'0')+'0';break;//加0是因为函数类型是OperandType(aka char),所以需要返回一个char类型的数 
		case'-':return (a-'0')-(b-'0')+'0';break;
		case'*':return (a-'0')*(b-'0')+'0';break;
		case'/':return (a-'0')/(b-'0')+'0';break;
	}
}

//#endif

Expression-Test.cpp文件 

/************************************
	文件路径:3 栈和队列\Expression 
	文件名称及类型:Expression-Test.cpp
	实现功能:表达式求值测试 
	writing time: 2018.8.12
************************************/

#include"Expression.cpp"

int main(){
	printf("请输入要计算的表达式(输入的值要求在0-9之间):\n");
	printf("结果为:%c\n",EvaluateExpression());
	
	return 0;
}

 实验结果

表达式求值_第1张图片

Note:本程序只能输入0-9以内的数字,如果输入两位数,将会出现下边这种情况导致程序没办法算出正确答案 

表达式求值_第2张图片

你可能感兴趣的:(严蔚敏数据结构课本,C/C++)