栈的应用实例4—表达式求值

栈的应用实例4—表达式求值

  • 这里用栈的特殊结构实现了算术的四则运算:先乘除后加减,从左算到右。输入格式举例:#4+2*3-10/5#(#为句子的开始或结束符号)。这里我偷了个懒,并没有实现改变优先级的 “(” 和 “)” ,原理一样。
  • 首先定义了两个栈,一个为运算符栈,一个为操作数栈。思路简单来说即为:
     ①.构造一个算符优先关系表,开始符号进栈,第一个操作数进栈。
     ②.当运算符进栈的时候,与算符栈的栈顶符号比较优先级,若优先级大于它则将运算符进栈,下一个操作数进栈,重复②;若当前运算符的优先级不大于算符栈的栈顶运算符,则它暂时不进栈,执行③。
     ③.将算符栈的栈顶运算符与操作数栈的栈顶及次栈顶元素进行计算,使它们都出栈,把计算结果进操作数栈,重复③直到②满足;若算符栈的栈顶运算符为 “#” 结束符号,则计算完成,清空两个栈,打印计算结果。
#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;

#define STACK_INIT_SIZE 100   //栈的初始化容量 
#define STACK_INC_SIZE 10	  //栈的分配增量 

typedef int elemType;

//栈的数据结构
typedef struct{
	elemType* base;  //栈底指针 
	elemType* top;	//栈顶指针 
	int stackSize;	//当前已分配的栈总存储空间 
}SqStack; 

void initStack(SqStack& S);  		 //构造空栈并初始化 
void pushStack(SqStack& S,elemType data); //数据元素进栈
void popStack(SqStack& S);  		 //数据元素出栈 

void initStack(SqStack& S)
{ 
	S.base=(elemType*)malloc(STACK_INIT_SIZE * sizeof(elemType));
	if(!S.base)  exit(1);
	S.top=S.base;
	S.stackSize=STACK_INIT_SIZE;  
} 

void pushStack(SqStack& S,elemType data)
{
	if(S.top-S.base>=S.stackSize) //栈满,扩充容量 
	{
		S.base=(elemType*)realloc(S.base,(S.stackSize+STACK_INC_SIZE) * sizeof(elemType));
		if(!S.base)  exit(1);
		S.top=S.base+S.stackSize; //栈顶改变
		S.stackSize+=STACK_INC_SIZE;
	}
	*S.top=data;
	S.top++;
}

void popStack(SqStack& S)
{
	if(S.top!=S.base)
	{ 
		S.top--;
	} 
}

void printStack(SqStack& S)
{
	cout<<"栈中的内容为:";
	for(elemType* i=S.base;i<S.top;i++)
	{
		int j=0;
		cout<<*(i+j)<<"  "; 
		j++;
	}
	cout<<endl;
}
				   //(i,j)对应的值表示下一个运算符与栈顶运算符的逻辑关系 
				   //+  -  *  /  (  )  #   :0为不存在,1为小于,2为大于,3为等于 
int opfirst[7][7]={
				  { 1, 1, 1, 1, 1, 2, 2 },  // +:43
				  { 1, 1, 1, 1, 1, 2, 2 },  // -:45
				  { 2, 2, 1, 1, 1, 2, 2 },  // *:42
				  { 2, 2, 1, 1, 1, 2, 2 },  // /:47
				  { 1, 1, 1, 1, 1, 3, 0 },  // (:40
				  { 2, 2, 2, 2, 0, 2, 2 },  // ):41
				  { 1, 1, 1, 1, 1, 0, 3 }   // #:35
};

int mid=0; 

void calFunction(SqStack& SF,SqStack& SS,char c)
{
	int i,j;
	//通过switch获得到i和j,在数组中查询两个运算符之间的优先级 
	switch(c)
	{
		case '+': i=0; break;
		case '-': i=1; break;
		case '*': i=2; break;
		case '/': i=3; break;
		case '(': i=4; break;
		case ')': i=5; break;
		case '#': i=6; break;
	}
	switch(*(SF.top-1))
	{
		case '+': j=0; break;
		case '-': j=1; break;
		case '*': j=2; break;
		case '/': j=3; break;
		case '(': j=4; break;
		case ')': j=5; break;
		case '#': j=6; break;
	}
	if(opfirst[i][j]==2)  //若下一个运算符优先级大于栈顶运算符,则进栈
	{
		pushStack(SF,c);
		cin>>i;
		pushStack(SS,i);  //后一个算数进栈
		cin>>c;
		if(c!='#')  //c不为结束符则继续调用该函数 
		{
			calFunction(SF,SS,c);  
		}
		else //否则计算中间结果,SF栈顶运算符出栈,SF栈顶操作数出栈,SF栈顶操作数出栈 
		{ 
			for(;;)
			{
				switch(*(SF.top-1))
				{
					case '+': mid=(*(SS.top-2))+(*(SS.top-1)); break;
					case '-': mid=(*(SS.top-2))-(*(SS.top-1)); break;
					case '*': mid=(*(SS.top-2))*(*(SS.top-1)); break;
					case '/': mid=(*(SS.top-2))/(*(SS.top-1)); break;
					case '(': i=4; break;
					case ')': i=5; break;
					case '#': i=6; break;
				}
				popStack(SF);
				popStack(SS);
				popStack(SS);
				pushStack(SS,mid);
				if(*(SF.top-1)=='#')  //直到结束,清空栈,输出计算结果 
				{
					popStack(SF);
					popStack(SS);
					cout<<"计算结果为:"<<mid<<endl;
					exit(0);
				}
			}
		}
	} 
	//若下一个运算符优先级小于栈顶运算符,则暂时不进栈,计算中间结果,直到下一个运算符优先级大于栈顶运算符
	else if(opfirst[i][j]==1||opfirst[i][j]==3)
	{
		switch(*(SF.top-1))
		{
			case '+': mid=(*(SS.top-2))+(*(SS.top-1)); break;
			case '-': mid=(*(SS.top-2))-(*(SS.top-1)); break;
			case '*': mid=(*(SS.top-2))*(*(SS.top-1)); break;
			case '/': mid=(*(SS.top-2))/(*(SS.top-1)); break;
			case '(': i=4; break;
			case ')': i=5; break;
			case '#': i=6; break;
		}
		popStack(SF);
		popStack(SS);
		popStack(SS);
		pushStack(SS,mid);
		calFunction(SF,SS,c);
	}
}

int main()
{
	//表达式求值: + - * / 
	SqStack SS,SF;     //定义算数栈SS,算符栈SF 
	initStack(SS);  
 	initStack(SF);
 	char c;
	int i;
	cin>>c;
	pushStack(SF,c);  //运算符进栈  #:40进栈  
	cin>>i;
	pushStack(SS,i);  //前一个算数进栈 
	cin>>c;
	calFunction(SF,SS,c);
	return 0;
}

运行结果:
/
/

发布了77 篇原创文章 · 获赞 19 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42932834/article/details/91357936