表达式转换[天梯赛 --- 栈]

题目描述

在这里插入图片描述

输入样例1
2+3*(7-4)+8/4
输出样例1
2 3 7 4 - * + 8 4 / +

输入样例2
((2+3)*4-(8+2))/5	
输出样例2
2 3 + 4 * 8 2 + - 5 /

输入样例3
1314+25.5*12
输出样例3
1314 25.5 12 * +

输入样例4
-2*(+3)	
输出样例4
-2 3 *

输入样例5
123
输出样例5
123

思路

栈模拟

注意:
栈内只存放字符,数字直接输出
具体流程中提到的:“运算符是数字的”表示形如-1这类的情况
具体流程:判断当前一位是什么
1.数字:继续向后判断,直到找到不是数字的且不是小数点的 —>多位数字 和 小数
2.字符:
①+ 或 - ,需要是不是在表达式开头出现,如果是,则该“运算符是数字的”;如果前一位不是数字,且不是右括号,则运算符也是数字的;除此之外,运算符就是单纯的运算符,直接入栈即可,但要保证栈顶到栈底的运算符优先级为单调递减
②* 或 /,直接入栈,但要保证栈顶到栈底的运算符优先级为单调递减
3.左括号,直接入栈
4.右括号,弹出一对括号内的字符

AC代码

#include <bits/stdc++.h>
using namespace std;
string s;
stack<char> op; //存放字符栈 
map<char, int> mp; //映射符号优先级 
vector<string> res; //末尾不允许有空格,因此使用res数组将结果存储下来 
int ed; //当遇到数字时,ed为指向数字最后一位的指针 
int len; //表达式长度 

void Init() //符号优先级初始化 
{
	mp['+'] = 0;
	mp['-'] = 0;
	mp['*'] = 1;
	mp['/'] = 1;
}

bool Judge_Num(char c) //判断当前字符是否为数字 
{
	return c >= '0' && c <= '9';
}

bool Judge_op(char c) //判断是否为符号 
{
	return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')';
} 

string Find_Num(int be) //寻找数字 
{
	while(ed < len && (Judge_Num(s[ed]) || s[ed] == '.')) ed ++; //整数或小数 
	return s.substr(be, ed - be);
} 

string char_to_string(char c) //将运算字符映射为运算字符串,便于存放进res数组 
{
	if(c == '-') return "-";
	if(c == '+') return "+";
	if(c == '*') return "*";
	if(c == '/') return "/";
}

int main()
{
	Init();
	getline(cin, s);
	len = s.size();
	
	for(int i = 0; i < len; i ++)
	{
		//如果当前一位为数字,这个判断只考虑多位数字和小数的情况 
		if(Judge_Num(s[i])) 
		{
			ed = i + 1;
			res.push_back(Find_Num(i));
			i = ed - 1; //此时ed指向的字符不为数字,但for循环还要执行一次i++的操作,因此i = ed - 1, 在执行一次i++就变为ed了 
		}
		
		//如果当前一位为字符,可能是运算符如 1+2, 或者为数字的字符如-1 
		else if((s[i] == '+' || s[i] == '-') && i + 1 < len && Judge_Num(s[i + 1])) //当前符号为正负号,且后面一位存在,为数字 
		{
			if(i == 0) //正负号出现在开头, 则该符号不是运算符 
			{
				string c = "" ;
				if(s[i] == '-') c = "-"; //只输出负号,正号不输出
				ed = i + 1;
				res.push_back(c + Find_Num(i + 1));
				i = ed - 1; //同上 
			}
			else //正负号不在开头 
			{
				if(!Judge_Num(s[i - 1]) && s[i - 1] != ')')
				{
					ed = i + 1; 
					string c = char_to_string(s[i]);
					if(c == "-") res.push_back(c + Find_Num(i + 1)); //这里只保留负号,正号不处理,如+3处理为3 
					else res.push_back(Find_Num(i + 1));
					i = ed - 1; 
				}
				else
				{
					while(op.size() && op.top() != '(' && mp[op.top()] >= mp[s[i]]) 
					{
						res.push_back(char_to_string(op.top()));
						op.pop();
					}
					op.push(s[i]);
				}
			}
		} 
		else if(s[i] == '(') op.push('(');  
		else if(s[i] == ')')
		{
			while(op.size() && op.top() != '(') 
			{
				res.push_back(char_to_string(op.top()));
				op.pop();
			}
			op.pop();
		}
		else 
		{
			while(op.size() && op.top() != '(' && mp[op.top()] >= mp[s[i]])
			{
				res.push_back(char_to_string(op.top()));
				op.pop();
			}
			op.push(s[i]);
		}
	}
	while(op.size())
	{
		res.push_back(char_to_string(op.top()));
		op.pop();
	}
	for(int i = 0; i < res.size(); i ++) 
	{
		if(i != res.size() - 1) cout << res[i] << " ";
		else cout << res[i] << endl;
	}
	return 0;
}

欢迎大家批评指正!!!

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值