今天又遇到了一个很扰人的问题,坑很大,于是决定把这个问题记录下来。
(点击图片放大查看)
这里题意的意思是读入表达式树的先序遍历字符串,也就是根据对应四个数字(值在1到13之间)组成的表达式,问该表达式树能不能得到24。
这个题目看似简单,但是却有很大的坑。
这里 表达式树的求值 的方法前面已经写出:表达式树的值(点击查看)。
当我修改表达树的值的代码然后直接上交时却发现 答案错误!
然后我查看错误再去检查代码百思不得其解。
同时又同学也出现此错误,便一起探讨,然后发现题目有坑啊!!
随后我们发现错误的地方。网站测试的数据里出发居然用了浮点型,而前面的 表达式树的值 却指定用的是int类型。不得不说:讲究!
但是由于是浮点型总是有不确定的位数,这里的判断条件(result==24)需要改动一下下;为了控制在比较准确的精度内而又同时通过测试,判断条件可改为(result>=23.9 && result<=24.1)。
还有在递归的时候如果除数是0时便返回一个很大或者很小的数字使之结果不能等于24.
源码与注释:
#include <bits/stdc++.h> //#include <iostream> //#include <stdio.h> using namespace std; string s; typedef struct Node{ float data; struct Node* left; struct Node* right; }Node; void Build(Node* &tree){//建立二叉树 cin>>s; float i=0,sn=0,len=0; if(s[0]=='#') tree=NULL; //空叶子 else{ //节点操作判断 if(s[0]=='+') sn=-1; else if(s[0]=='-') sn=-2; else if(s[0]=='*') sn=-3; else if(s[0]=='/') sn=-4; else{ //叶子节点操作数计算 len=s.size(); //printf("%d ",len); //输出字符串s的长度 while(i<len){ if(s[i]=='A') sn=sn*10+1; else if(s[i]=='J') sn=sn*10+11; else if(s[i]=='Q') sn=sn*10+12; else if(s[i]=='K') sn=sn*10+13; else sn=sn*10+(s[i]-'0'); i++; } } tree=new Node; tree->data=sn; Build(tree->left); //递归建立左子树 Build(tree->right); //递归建立右子树 } } void Print_Tree(Node* tree){ //打印表达式 if(tree){ if(tree->data>=0) printf("%d",tree->data); //如果遇到叶子节点直接输出 else{ printf("("); //打印左括号 Print_Tree(tree->left); //打印左子树 if(tree->data==-1) printf("+"); //打印操作符 else if(tree->data==-2) printf("-"); else if(tree->data==-3) printf("*"); else if(tree->data==-4) printf("/"); Print_Tree(tree->right); //打印右子树 printf(")"); //打印右括号 } } } float Cal_Tree(Node* tree){ //计算表达式树 if(tree){ if(tree->data>=0){ return tree->data; } else{ //int sn=Cal_Tree(tree->left); if(tree->data==-1){ return Cal_Tree(tree->left) + Cal_Tree(tree->right); } else if(tree->data==-2){ return Cal_Tree(tree->left)-Cal_Tree(tree->right); } else if(tree->data==-3){ return Cal_Tree(tree->left) * Cal_Tree(tree->right); } else if(tree->data==-4){ if(Cal_Tree(tree->right)) return Cal_Tree(tree->left) / Cal_Tree(tree->right); else return 233333333333; } } } } int main() { //char ch; while(cin>>s) //输入string字符串,默认空格结束 { //cout<<s; float i=0,sn=0,len=0; if(s[0]=='+') sn=-1; //操作符判断 else if(s[0]=='-') sn=-2; else if(s[0]=='*') sn=-3; else if(s[0]=='/') sn=-4; else{ //操作数判断 len=s.size(); //printf("%d ",len); while(i<len){ if(s[i]=='A') sn=sn*10+1; else if(s[i]=='J') sn=sn*10+11; else if(s[i]=='Q') sn=sn*10+12; else if(s[i]=='K') sn=sn*10+13; else sn=sn*10+(s[i]-'0'); i++; } } Node* tree=new Node; tree->data=sn; //叶子节点 Build(tree->left); //递归建立左子树 Build(tree->right); //递归建立右子树 //Print_Tree(tree); //打印表达式 sn=Cal_Tree(tree); //计算表达式树的值 if(sn>=23.9 && sn <= 24.1){ //在误差内的判断 Print_Tree(tree); printf("=24"); } else printf("NO"); printf(" "); //输出空行 } return 0; }