中缀表达式转后缀表达式并求值(多位数)

中缀表达式转后缀表达式并求值(多位数)

一、问题简述

  • 中缀表达式:是一种通用的算术或逻辑公式表示方法,操作符处于操作数的中间。中缀表达式是人们常用的算术表示方法,如3+5*8。
  • 后缀表达式(逆波兰表达式):运算符位于两个相应操作数之后,更方便计算机的运算,如3 5 8 * +。
  • 为了方便计算机的运算,我们需要把中缀表达式转成后缀表达式。(也可直接计算中缀表达式的值)

二、背景题目:中缀表达式的值(北大oj平台)

  • 描述

    人们熟悉的四则运算表达式称为中缀表达式,例如(23+34*45/(5+6+7))。在程序设计语言中,可以利用堆栈的方法把中缀表达式转换成保值的后缀表达式(又称逆波兰表示法),并最终变为计算机可以直接执行的指令,得到表达式的值。 给定一个中缀表达式,编写程序,利用堆栈的方法,计算表达式的值。

  • 输入

    第一行为测试数据的组数N 接下来的N行,每行是一个中缀表达式。表达式中只含数字、四则运算符和圆括号,操作数都是正整数,数和运算符、括号之间没有空格。中缀表达式的字符串长度不超过600。

  • 输出

    对每一组测试数据输出一行,为表达式的值

  • 样例输入

    3
    3+5*8
    (3+5)*8
    (23+34*45/(5+6+7)) `
    
  • 样例输出

    43
    64
    108
    
  • 提示

    注意:运算过程均为整数运算(除法运算’/'即按照C++定义的int除以int的结果,测试数据不会出现除数为0的情况),输出结果也为整数(可能为负)。 中间计算结果可能为负。

三、表达式转换思路

  • 多位数的计算与一位数的计算有差别:需要将字符串表达式中的多位数字分出来(下面代码中的初始化部分)。用vector来接收分解出string表达式中的数字和字符。
  • string_to_int函数将字符串数组中的数字部分转为int类型用于表达式的计算。
  • 中缀转后缀:扫描已初始化后的字符串数组,建立一个辅助栈和存储后缀表达式的字符串数组。
    1. 当遇到数字时:直接输出,即push_back到辅助字符串数组。
    2. 当遇到操作符时(该操作符不是右括号):如果栈空就直接入栈;如果栈不为空,则用该 操作符与栈顶的操作符作比较,若操作符优先级比栈顶操作符优先级高,直接入栈,否则弹栈并输出直到栈为空或遇到优先级更低的操作符 (除了左括号),再将该操作符入栈。
    3. 当遇到右括号:顺序出栈并输出(入辅助字符串数组)直到遇到左括号,最后将左括号出栈,不输出左括号。
    4. 扫描结束后:将栈中所有元素出栈并输出(入辅助字符串数组)。

四、后缀表达式计算

  • 扫描中缀表达式转换后的后缀表达式,建立一个辅助栈。
    1. 若遇到数字,将其转成int类型并入辅助栈。
    2. 若遇到操作符就从栈顶出栈两个元素并进行相应的运算,将结果再入栈。
    3. 依次进行,最后的栈顶元素即为表达式的结果。

五、代码实现

#include<iostream>
#include<string>
#include<stack>
#include<cstdlib> 
#include<sstream> 
#include<vector>
using namespace std; 


int string_to_int(string a){
	stringstream ss;
	int s;
	ss<<a;
	ss>>s;
	return s;
}

int judge(string a){
	if(a=="+"||a=="-")	
		return 1;
	else if(a=="*"||a=="/")  
		return 2;
	else if(a=="(")	
		return 3;
	else if(a==")")	
		return -1;
	else 
		return 0;
}

vector<string> chu_shi_hua(string s){//初始化 
	vector<string>a;
	int j,i;
	i=0;
	while(i<s.size())
	{	j=i;
		
		while(j<s.size()&&s.at(j)<='9'&&s.at(j)>='0'){
			j++;
		}
		if(i==j){
			a.push_back(s.substr(i,1));
			i=i+1;
			
		}
		
		else{
			a.push_back(s.substr(i,j-i));
			i=j;
		}	
	}
	return a;
}


int calculate(vector<string> s){
	stack<int> result;
	int a,b;
	for(int i=0; i<s.size();i++){
		
		if(judge(s[i])==0)
			result.push(string_to_int(s[i]));
		else{
			a=result.top();
			result.pop();
			b=result.top();
			result.pop();
			if(s[i]=="+")
				result.push(b+a);
							
			if(s[i]=="-")
				result.push(b-a);
							
			if(s[i]=="*")
				result.push(a*b);
							
			if(s[i]=="/")
				result.push(b/a);
		}	
		
	}
	return result.top();
}

vector<string>  zhong_hou(vector<string> s){
	stack<string> result;
	vector<string> save;
	for(int i=0; i<s.size();i++){
		
		if(judge(s[i])==0)//遇到数字就直接输出
			save.push_back(s[i]);
			
		if(judge(s[i])>0){
			
			if(result.empty())//栈为空则直接压栈 
				result.push(s[i]);
			
			else{
				
				if(judge(s[i])>judge(result.top()))//操作符优先级比栈顶操作符优先级高
				{	result.push(s[i]);
					}	
				
				else{
					while((!result.empty())&&judge(result.top())>=judge(s[i])&&result.top()!="(")//弹栈并输出直到栈为空或遇到优先级更低的操作符 (除了左括号)
					{	
						save.push_back(result.top());
						result.pop();
					}
					result.push(s[i]);
				}
				
			}
			
		}
		
		if(judge(s[i])==-1){
			while(result.top()!="("){
				save.push_back(result.top());
				result.pop();
			}
			result.pop();			
		}
	}
	
	while(!result.empty()){
		save.push_back(result.top());
		result.pop();
		
	}

	return save;
	
	 
}



int main(){
	int n;
	string s1;//s1表达式 
	vector<string> s2,s3;//s2是初始化后的表达式,将多位的数字分出来。s3是后缀表达式 
	cin>>n;
	while(n--){
		cin>>s1;
		s2=chu_shi_hua(s1);
		s3=zhong_hou(s2);
		cout<<calculate(s3)<<endl; 
	}
	
	return 0;
}
  • 10
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您编写一个函数,实现中缀表达式转后缀表达式,并计算最后的结果。以下是一个示例代码: ```python def infix_to_postfix(expression): # 定义运算符的优先级 precedence = {'+': 1, '-': 1, '*': 2, '/': 2} postfix = [] # 存储后缀表达式 stack = [] # 运算符 for char in expression: if char.isdigit(): postfix.append(char) elif char in '+-*/': while stack and stack[-1] != '(' and precedence[char] <= precedence.get(stack[-1], 0): postfix.append(stack.pop()) stack.append(char) elif char == '(': stack.append(char) elif char == ')': while stack and stack[-1] != '(': postfix.append(stack.pop()) stack.pop() # 弹出左括号 while stack: postfix.append(stack.pop()) return postfix def evaluate_postfix(postfix): stack = [] for char in postfix: if char.isdigit(): stack.append(int(char)) elif char in '+-*/': num2 = stack.pop() num1 = stack.pop() if char == '+': stack.append(num1 + num2) elif char == '-': stack.append(num1 - num2) elif char == '*': stack.append(num1 * num2) elif char == '/': stack.append(num1 / num2) return stack[0] def calculate(expression): postfix = infix_to_postfix(expression) result = evaluate_postfix(postfix) return result ``` 您可以调用 `calculate` 函数,并将中缀表达式作为参数传入。函数将返回计算结果。例如: ```python expression = "3 + 4 * 2 / ( 1 - 5 )" result = calculate(expression) print(result) # 输出结果为 1.0 ``` 请注意,以上代码只支持单个数字的计算,如果需要支持多位数的计算,需要对输入表达式进行解析和拼接。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值