例-2 后缀式求值 (25 分)

例-2 后缀式求值 (25 分)

我们人类习惯于书写“中缀式”,如 3 + 5 * 2 ,其值为13。 (p.s.为什么人类习惯中缀式呢?是因为中缀式比后缀式好用么?) 而计算机更加习惯“后缀式”(也叫“逆波兰式”,Reverse PolishNotation)。上述中缀式对应的后缀式是: 3 5 2 * + 现在,请对输入的后缀式进行求值。

输入格式:

在一行中输入一个后缀式,运算数和运算符之间用空格分隔,运算数长度不超过6位,运算符仅有+ - * / 四种。

输出格式:

在一行中输出后缀式的值,保留一位小数。

输入样例:

3 5.4 2.2 * +

输出样例:

14.9

分析

这是一道基本的数据结构题了,我这个小白,没学过STL,不会使用那些栈啊,队列啥的。可不会,咱不能闲着,咱得学啊。

总体的思路:
由于已经是后缀式,那就把数和运算符都统统入到队列中去;
在计算的时候,出队列:如果是数,入栈,如果是操作符,那就出栈,先出的在后面,后出栈的放前面;算完后的结果再放入栈中。

我踩的坑:

  1. 数和操作符不知道怎么分开;
  2. 有小数该怎么算出正确的操作数;
  3. ‘-’这个可以代表减号 还可以代表 负号,没有考虑到;

代码

#include
#include
#include
#include 
#include 
using namespace std;
/*这个题我一看,这个咋整啊, 这是要用到栈还是队列,我可不会用STL啊,你看这个运算符还分两种类型
  一种为运算数,还有运算符。这个我该如何判断它是运算符还是运算数呢?啊,苍天啊!
  没有办法,我要先把数据存下来;然后在进行处理; 
*/
//考虑错了,可以借助结构体,来实现两种类型同时在队列中;

struct node
{
	double num;
	char op;
	bool isNum ; //如果是数为true,是操作数flase 
}; 

int main()
{
	string str;	
	getline(cin,str);
	double num;
	char op;
	
	stack s;
	queue q;
	
	bool isDot ;
	int indexofi;
	double numInDot;   //坑爹啊,一开始定义成了int 类型,死活没小数啊;
	
	// 下面来先把数和运算符区分开 
	 node temp;
    if(str !="0")
    {
    	for(int i = 0; i< str.length();)
    	{
    		if(str[i] >= '0' && str[i] <= '9')  //是数字 
    		{
    			temp.isNum = true;
    			isDot = false;
    			temp.num = str[i++] - '0' ;	
    			numInDot = 1;
    			while(i < str.length() && str[i] != ' ')  //空格符结束 
    			{
    				if(!isDot )                           //看是否有小数点 
    				{
    					if(str[i] != '.' ) temp.num = temp.num * 10 + (str[i] - '0');  
    					else
    					{
    						isDot = true;
    						indexofi = i;
						}
					}
					else                              // 有小数点 
					{
						
						numInDot = (str[i] - '0');
						for(int j = i ; j> indexofi; j--)
						{
							numInDot *= 0.1
						}
						
						temp.num +=numInDot;   // 加上小数部分 
					}
					i++; 
				}
				q.push(temp);
			}
			else
			{
				if(str[i]== '-')  //可能是负数 ,也可能是减号 
				{
					if(i+1 < str.length() && (str[i+1]>= '0' && str[i+1] <= '9')) //负数符号 
					{
						temp.isNum = true;
						temp.num = str[++i] - '0';
						isDot = false;
						numInDot = 1;
						i++;
						
    					while(i < str.length() && str[i] != ' ')  //空格符结束 
    					{
    						if(!isDot )                           //看是否有小数点 
    						{
    							if(str[i] != '.' ) temp.num = temp.num * 10 + (str[i] - '0');  
    							else
    							{
    								isDot = true;
    								indexofi = i;
								}
							}
							else                              // 有小数点 
							{
						
								numInDot = (str[i] - '0');
								for(int j = i ; j> indexofi; j--)
								{
					 
									numInDot *= 0.1;
					
								}
								
								temp.num +=numInDot;   // 加上小数部分 
						
							}
							i++; 
						}
		
						temp.num = -temp.num;  // 因为是负数,所以要加负号; 
						
						q.push(temp);
					}
					else
					{
						temp.isNum =false;
						temp.op = str[i];
						q.push(temp);	
					} 
				}
				else if(str [ i] == '+' || str [ i] == '*' || str [ i] == '/')
				{
					temp.isNum = false;
					temp.op = str[i];
					q.push(temp);
				}
				 
				i++;
			}
		}
	}
// 开始运算了;

	double sum =0;
	
	double tem1,tem2;
	node cur;

	while(!q.empty())
	{
		cur = q.front();
		q.pop();
		if(cur.isNum == true) s.push(cur); //数的话进去
		else
		{
			tem1 = s.top().num;
			if(!s.empty())s.pop();
			tem2 = s.top().num;
			if(!s.empty())s.pop();
			
			temp.isNum = true; //算出的结果还要在压入到栈中;
			
		
				if(cur.op == '-')
					temp.num = tem2 - tem1;	
				else if(cur.op == '+')
					temp.num = tem2 + tem1;
				
				else if(cur.op == '*')
					temp.num = tem2 * tem1;
					
				else if(cur.op == '/')
					temp.num = tem2 / tem1;
			
			s.push(temp);	
		} 
	}
if(!s.empty())	
printf("%.1f\n",s.top().num);
return 0;
} 

好吧,虽然我是个计算机专业的学生,但是我得承认我是个学渣。这道题我用了大概半天的时间才完全弄明白。特别是那个负号没考虑到的时候,提交到PAT,显示段错误,我完全是萌萌哒好嘛!!!
哎呀,前几年偷得懒,现在得还了啊!!!!

你可能感兴趣的:(数据结构与算法实战)