中缀表达式转换成后缀表达式

中缀表达式转换成后缀表达式

题目:所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右进行
例1:中缀表达式: 3*(5–2)+7 对应的后缀表达式为:352-*7+
例2:中缀表达式: 2+48+(88+1)/3 对应的后缀表达式为 248+881+3/+
考察内容:栈的基本使用

以下解题默认输入的中缀表达式是正确的,即都有解(不考虑分母是0的情况等)。
第一版源代码:

#include<iostream>
#include<vector>
#include<stack>
#include<string>
using namespace std;
int value(char c)
{
	switch(c)//优先级:乘除>加减>左括号 
	{
		case'(':return 1;break;
		case'+':
		case'-':return 2;break;
		case'*':
		case'/':return 3;break;
	}
}

string change(string a)
{
	string str;
	stack<char>data;
	int len=a.length();
	for(int i=0;i<len;i++)
	{
		//(1) 如果遇到数字,直接放到后缀表达式尾
		if(a[i]>='1'&&a[i]<='9')
		{
			str+=a[i];
		}
		//(2) 如果遇到遇到运算符 
		else
		{
			if(a[i]=='(')//a.若当前运算符为'('直接入栈
			{
				data.push(a[i]);
			}
			else if(a[i]==')')//b.若当前运算符为’)’则将栈顶元素出栈置于后缀表达式尾, 直到遇到运算符’(‘, 注意’(’ 与 ‘)’不用置于后缀表达式尾
			{
				while(data.top()!='(')
				{
					str+=data.top();
					data.pop();
				}
				data.pop();
			}
			else if(data.empty())//c.若此时栈空,则直接入栈
			{
				data.push(a[i]);
			}
			else 
			{
				if(value(a[i])>value(data.top()))data.push(a[i]);//d.若栈stack不空且当前运算符优先级大于栈顶运算符优先级,则将此运算符直接入栈
				else
				{
					while(value(a[i])<=value(data.top()))//e,循环:若栈stack不空且当前运算符优先级小于或等于栈顶运算符的优先级,则将栈顶运算符依次出栈,置于后缀表达式尾
					{
						str+=data.top();
						data.pop();
						if(data.empty())break;
					}
					data.push(a[i]);
				}
			}
		}	
	}
	//(3)若此时栈stack不为空, 则将栈顶运算符依次出栈置于后缀表达式尾.
	if(!data.empty())
	{
		while(!data.empty())
		{
			str+=data.top();
			data.pop();
		}
	}
	return str;
}

int main()
{
	string a;
	cin>>a;
	cout<<"中缀表达式:"<<a<<endl;
	string b=change(a);
	cout<<"后缀表达式:"<<b<<endl; 
	return 0;
 } 

运行结果:
在这里插入图片描述
代码缺陷

  1. 这样的后缀表达式似乎无法求值,那不就失去意义了?或许需要把两个数用空格分开?
  2. 没考虑负数的情况,负号和减号似乎有点难区分?运算符后又跟着一个‘-’,这是负号?
    针对以上问题,本小白又做了些改进~(顺便也把求值结果也给求了)

第二版源代码:

#include<iostream>
#include<vector>
#include<stack>
#include<string>
using namespace std;
int value(char c)
{
	switch(c)//优先级:乘除>加减>左括号 
	{
		case'(':return 0;break;
		case'+':
		case'-':return 1;break;
		case'*':
		case'/':return 2;break;
	}
}
string change(string a)
{
	string str;
	stack<char>data;
	int ret=1;//用来判断'-'是减号还是负号 ,这里设置1是负号,0是减号 
	int len=a.length();
	for(int i=0;i<len;i++)
	{
		//(1) 如果遇到数字,直接放到后缀表达式尾
		if(a[i]>='0'&&a[i]<='9')
		{
			str+=a[i];
			ret=0;//接在数字后面的'-'只能是减号 
			if(a[i+1]=='+'||a[i+1]=='-'||a[i+1]=='*'||a[i+1]=='/'||a[i+1]=='('||a[i+1]==')')str+=' ';
		}
		//(2) 如果遇到遇到符号 
		else
		{
			if(a[i]=='(')//a.若当前运算符为'('直接入栈
			{
				data.push(a[i]);
			}
			else if(a[i]==')')//b.若当前运算符为’)’则将栈顶元素出栈置于后缀表达式尾, 直到遇到运算符’(‘, 注意’(’ 与 ‘)’不用置于后缀表达式尾
			{
				while(data.top()!='(')
				{
					str+=' ';
					str+=data.top();
					str+=' ';
					data.pop();
				}
				data.pop();
			}
			else//如果遇到运算符 
			{ 
				if(ret)
				{
					data.push(a[i]);
					ret=0;
				}
				else
				{
					if(data.empty())data.push(a[i]);//c.若此时栈空,则直接入栈
					else 
					{
						if(value(a[i])>value(data.top()))data.push(a[i]);//d.若栈stack不空且当前运算符优先级大于栈顶运算符优先级,则将此运算符直接入栈
						else
						{
							while(value(a[i])<=value(data.top()))//e,循环:若栈stack不空且当前运算符优先级小于或等于栈顶运算符的优先级,则将栈顶运算符依次出栈,置于后缀表达式尾
							{
								str+=' ';
								str+=data.top();
								str+=' ';
								data.pop();
								if(data.empty())break;
							}
							data.push(a[i]);
						}
					}
					ret=1;
				}
			} 
		}		
	}
	//(3)若此时栈stack不为空, 则将栈顶运算符依次出栈置于后缀表达式尾.
	if(!data.empty())
	{
		while(!data.empty())
		{
			str+=' ';
			str+=data.top();
			str+=' ';
			data.pop();
		}
	}
	return str;
}

long long int calculate(string str)
{
	stack<long long int>data;
    long long int c1,c2;
    int n=str.length();
    long long int num=0;//num用来记录每个数字的大小 
	int ret=0,fu_ret=0;//ret用来记录数字是否存在 ,fu_ret用来记录数字是否为负数 
    for(int i=0;i<n;i++)
    {
		if(str[i]==' ')
        {
        	if(ret)
			{
				if(fu_ret)
				{
					data.push((-1)*num);
					num=0;
					ret=0;
					fu_ret=0;
				}
				else
				{
					data.push(num);
					num=0;
					ret=0;
				}
			}	
		}
    	else if(str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='/')
        {
        	
        	if(str[i]=='-'&&str[i+1]>='0'&&str[i+1]<='9')fu_ret=1;
        	else 
			{	
	            c1=data.top();
	            data.pop();
	            c2=data.top();
	            data.pop();
	            if(str[i]=='+')data.push(c2+c1);
	            if(str[i]=='-')data.push(c2-c1);    
	            if(str[i]=='*')data.push(c2*c1);
	            if(str[i]=='/')data.push(c2/c1);
			}
        }
        else
        {
        	num=num*10+str[i]-'0';
            ret=1;
        }
    }
    return data.top();
}
int main()
{
	string a;
	cin>>a;
	cout<<"中缀表达式:"<<a<<endl;
	string b=change(a);
	cout<<"后缀表达式:";
	int n=b.length();
	for(int i=0;i<n;i++)
	{
		if(b[i]!=' ')cout<<b[i];
	}
	cout<<endl;
	cout<<"result:"<<calculate(b)<<endl;
	return 0;
 } 

运行结果:
在这里插入图片描述
其实还并不清楚这种方法是如何想出的,只知道有这样一种解决四则运算问题的方法,还有待我继续思考呀
不过,参考了各方的材料,进行了总结,最后还是写完了代码~~(挺开心)
Emma,总觉得还有哪些bug?欢迎大家指出

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值