考研数据结构:用栈求中缀表达式的值(附C++代码)

数据结构:用栈求中缀表达式的值

一、思路:

  1. 定义两个栈:s1和s2,其中s1为操作数栈,用来存放操作数,s2为运算符栈,用来存放运算符。

  2. 定义一个操作(在下文中称为“运算操作”):从操作数栈s1中依次连续出栈两个操作数,第一个操作数在右,第二个操作数在左,再从运算符栈s2中出栈一个运算符放到两个操作数中间。最后将运算结果压入操作数栈s1中。

  3. 从左往右扫描中缀表达式:
    ①如果碰到操作数,则直接将其压入操作数栈s1中。
    ②如果碰到运算符:
    a·若运算符栈s2为空 或 运算符栈s2栈顶元素为左括号’(’ 或 当前运算符为左括号’(’,则直接将其压入运算符栈s2中。
    b·若当前运算符为右括号’)’,则循环执行“运算操作”,直至碰到左括号’(’,最后再将左括号’('出栈。
    c·若当前运算符不为上述两种情况,且不为括号。若当前运算符的优先级大于(>)运算符栈s2栈顶元素的优先级,则直接将当前运算符入栈;若当前运算符的优先级小于或等于(<=)运算符栈s2栈顶元素的优先级,则执行一次“运算操作”。

  4. 若运算符栈s2不为空,则一直执行“运算操作”,直至s2为空。

  5. 此时操作数栈s1的栈顶元素即为所求答案

二、C++ 代码

#include<iostream>
using namespace std;

const int maxSize = 1000;

//获取当前运算符的优先级 
int getPriority(char Op)
{
	if(Op == '+' || Op == '-') 
		return 0;
	else
		return 1;   //这样保证了乘和除的优先级大于加和减的优先级 
}

//两个操作数和一个运算符进行运算 
int op(int a, char Op, int b)
{
	if(Op == '+') return a + b;
	else if(Op == '-') return a - b;
	else if(Op == '*') return a * b;
	else
	{
		if(b == 0)	//注意除数不能为零,要特判 
		{
			cout << "ERROR : 除数为零!" << endl;
			return -1;
		}
		else
			return a / b;
	}
}

//"运算操作":从操作数栈s1中弹出两个元素,第一个在右,第二个在左,运算符栈s2中弹出一个运算符
//		三者进行op操作,最后将结果压入操作数栈s1中 
int act(int s1[], int &top1, char s2[], int &top2)
{
	int a, b, c;
	char Op;
	b = s1[top1 --];
	a = s1[top1 --];
	Op = s2[top2 --];
	c = op(a, Op, b);
	s1[++ top1] = c;
	return c;
}

int com(char exp[])
{
	int s1[maxSize], top1 = -1;      //定义操作数栈s1(整形),并初始化 
	char s2[maxSize]; int top2 = -1; //定义运算符栈s2(字符型),并初始化 
	
	for(int i = 0; exp[i] != '\0'; i ++)	//从左向右遍历exp[]数组 
	{
		if(exp[i] >= '0' && exp[i] <= '9')	//碰到数字 
			s1[++ top1] = exp[i] - '0';		//转化成整形后压入操作数栈s1中 
		else
		{
			if(
				top2 == -1 ||        //运算符栈s2为空 
				exp[i] == '(' ||   	//遇到左括号
				s2[top2] == '(' ||   //运算符栈顶为左括号
				(exp[i] != '(' && exp[i] != ')' && getPriority(exp[i]) > getPriority(s2[top2])) 
					//当前运算符不为括号并且优先级大于(>)s2栈顶元素优先级  	
			)
				s2[++ top2] = exp[i];  //以上四种情况直接将运算符压入运算符栈s2中 
			else if(exp[i] == ')')    //遇到右括号 
			{
				while(s2[top2] != '(')
					act(s1, top1, s2, top2);  //循环进行上面定义的"运算操作",直到碰到左括号。注:两个括号一定是匹配的 
				top2 --; 	//将左括号出栈,不用管它 
			}
			else if(getPriority(exp[i]) <= getPriority(s2[top2]))  //当前运算符不为括号并且优先级小于或等于(<=)s2栈顶元素优先级 
			{ 
				act(s1, top1, s2, top2);  //先执行一次"运算操作" ,将前面优先级高的部分进行计算 
				s2[++ top2] = exp[i];	  //再将当前运算符压入运算符栈s2中(易漏) 
			} 
		}
	}
	
	while(top2 != -1)	//如果运算符栈s2不空 
		act(s1, top1, s2, top2);  	//将运算符栈s2中剩下的运算符全部进行计算 
	
	return s1[top1];   //最后操作数栈s1的栈顶元素即为所求答案 
}



int main()
{
	//示例:(1+2)*5+(3*6-2)*2
	char exp[20];
	for(int i = 0; i < 17; i ++) cin >> exp[i];
	exp[17] = '\0';
	cout << com(exp) << endl;
	return 0;
} 


代码运行结果

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值