中缀表达式转后缀表达式+四则运算编程-华为机试HJ50

1、中缀表达式转后缀表达式

在编程实现四则运算时,往往需要两个步骤:(1)将题目给的中缀表达式转为后缀表达式;(2)利用后缀表达式进行计算;

对于1+(2-3)*4+10/5

准备一个栈用于存放符号,对于数字就输出,对于符号A,如果A的优先级大于栈内符号,那么A就入栈,如果栈内没有比A优先级小的符号,那么栈内的符号就出栈,再把A入栈。对于括号就入栈,一直匹配到右括号再将括号里的符号出栈。另外,还需要把表达式的[]{}这些符号要提前转化为()。

1、输出1,+入栈,此时后缀表达式是1
在这里插入图片描述
2、此时遇到左括号,(要入栈;然后输出2;下一个-入栈;输出3;一直匹配到右括号,再把括号内的符号出栈。此时后缀表达式是1 2 3在这里插入图片描述
3、匹配到右括号,那么就把-弹出来;此时后缀表达式是1 2 3 -
在这里插入图片描述
4、下一个是乘号,优先级大于+号,入栈;此时后缀表达式是1 2 3 -
在这里插入图片描述

5、 接下来是4,输出;下一个是+号,此时栈内没有比它优先级小的符号,这样就把栈内的符号都弹出来,再把+入栈;此时后缀表达式是1 2 3 - 4 * +,栈里面就是+
在这里插入图片描述
在这里插入图片描述
6、接下来是10,输出;然后是/,大于栈内优先级,入栈;此时后缀表达式是1 2 3 - 4 * + 10
在这里插入图片描述
7、接下来是5,输出;此时栈内是/ +,全部输出;那么此时后缀表达式是1 2 3 - 4 * + 10 5 / +
在这里插入图片描述

2、HJ50

#include<iostream>
#include<string>
#include<stack>
#include<vector>
#include<sstream>
using namespace std;
//将大括号变成小括号,负数转化为0与之的差
void change(string &str)
{
	for (int i = 0; i < str.size(); ++i)
	{
		if (str[i] == '{')//将‘{、}、[,]’替换成'()'
			str[i] = '(';
		else if (str[i] == '}')
			str[i] = ')';
		else if (str[i] == '[')
			str[i] = '(';
		else if (str[i] == ']')
			str[i] = ')';
		else if (str[i] == '-')
		{
			if (i == 0)//将'-'前面添加0转变成减法运算
				str.insert(0, 1, '0');
			else if (str[i - 1] == '(')
				str.insert(i, 1, '0');
		}
	}
}
//根据当前遍历符号与栈顶元素的优先级判断符号是不是要出栈或进栈
//如果现在的优先级高输出false,否则输出true
bool Judge(char top, char now)
{
	if ((top == '+' || top == '-') && (now == '+' || now == '-'))
		return true;
	else if ((top == '*' || top == '/') && (now == '+' || now == '-' || now == '*' || now == '/'))
		return true;
	else if (now == ')')//以便去匹配此前的“(”
		return true;
	return false;
}
//将中缀表达式转换为后缀表达式
//用string无法处理连续数字
vector<string> z_h(string &str1)
{
	stack<char> sta;//初始化一空栈,用来对符号进出栈使用
	//string str2;//作为后缀表达式
	vector<string> str2;

	for (int i = 0; i < str1.size(); i++)
	{
		string temp = "";
		if (str1[i] >= '0' && str1[i] <= '9')//如果是数字就输出
		{
			temp += str1[i];
			while (i + 1 < str1.size() && str1[i + 1] >= '0' && str1[i + 1] <= '9')
			{
				temp += str1[i + 1];//若是连续数字
				++i;
			}
			str2.push_back(temp);
		}
		else if (sta.empty() || str1[i] == '(')//“(”,依然是符号,因其只是左括号,还没有配对,故进栈
			sta.push(str1[i]);
		else if (Judge(sta.top(), str1[i]))//若栈顶元素优先级较高,栈顶元素出栈
		{
			//接下来遇到符号“)”,需要去匹配此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止,将“(”
			//上面的符号依次输出到str2里面
			if (str1[i] == ')')
			{
				while (!sta.empty() && sta.top() != '(')
				{
					temp += sta.top();
					sta.pop();
					str2.push_back(temp);
					temp = "";
				}
				sta.pop();//将“(”弹出来
			}
			//接下来对于不是括号的,判断优先级,如果高就入栈,直到当前字符低于栈顶的优先级
			else
			{
				while (!sta.empty() && Judge(sta.top(), str1[i]))
				{
					temp += sta.top();
					sta.pop();
					str2.push_back(temp);
					temp = "";
				}
				sta.push(str1[i]);//优先级高于栈顶,入栈
			}
		}
		else//当前字符优先级更高
			sta.push(str1[i]);
	}
	//接下来,弹出剩余的运算符
	while (!sta.empty())
	{
		string temp = "";
		temp += sta.top();
		sta.pop();
		str2.push_back(temp);
	}
	return str2;
}
//通过获得的后缀表达式计算结果
int cal(vector<string> & str)
{
	stack<int> st3;//存放运算结果
	int temp1, temp2,num;//其中temp1和temp2为栈顶的两个数
	for (int i = 0; i < str.size(); i++)
	{
		string temp = str[i];
		if (temp[0] >= '0' && temp[0] <= '9')
		{
			stringstream ss;
			ss << temp;
			ss >> num;
			st3.push(num);
		}
		/*
		string temp=str[i];
		if(temp[0]>='0' && temp[0]<='9')//如果当前字符串是数字,利用字符串流转化为int型
		{
			stringstream ss;
			ss<<temp;
			ss>>num;
			st.push(num);
		}*/
		else
		{
			temp1 = st3.top();
			st3.pop();
			temp2 = st3.top();
			st3.pop();
			if (str[i] == "+") st3.push(temp1 + temp2);
			else if (str[i] == "-") st3.push(temp2 - temp1);
			else if (str[i] == "*") st3.push(temp2 * temp1);
			else if (str[i] == "/") st3.push(temp2 / temp1);
		}
	}
	return st3.top();
}
int main()
{
	string str;
	while (getline(cin, str))
	{
		vector<string> vstr;
		change(str);
		vstr=z_h(str);
		cout << cal(vstr);
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淮杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值