实现一个简单的计算器。通过键盘输入一个包含圆括号、加减乘除等符号组成的算术表达式字符串,输出该算术表达式的值。要求:
(1)系统至少能实现加、减、乘、除等运算;
(2)利用二叉树算法思想求解表达式的值,先构造由表达式构成的二叉树,然后再利用通过对二叉树进行后序遍历求解算术表达式的值。

#include <iostream>
#include <string>
#include <sstream>
#include <stack>
#include <cmath>
using namespace std;bool IsOperator(string mystring)   //判断字符串是否是运算符
{if(mystring == "-"||mystring == "+"||mystring == "*"||mystring == "/")return true;elsereturn false;
}bool IsOperator(char ops)  //判断一个字符是否是运算符
{if(ops == '+'||ops== '-'||ops== '*'||ops== '/'||ops=='('||ops==')')return true;elsereturn false;
}bool IsOperand(char ch)   //判断是否是数字
{if (((ch>='0')&&(ch<='9'))||(ch=='.'))return true;elsereturn false;
}bool judge(string exp)   //判断输入是否正确
{char check;int error=0,lb=0,rb=0,numofoperand=0,numofoperator=0;for(int m=0;m<exp.size();m++){check=exp[m];if(IsOperand(check)){if(check=='.')//判断浮点型数据是否正确{if(!(exp[m-1]>='0'&&exp[m-1]<='9')&&(exp[m+1]>='0'&&exp[m+1]<='9')){error++;cout<<"浮点型数据输入有误!!!"<<endl;}}numofoperand++;}else if(IsOperator(check)){if(check==')'){rb++;if(rb>lb){error++;cout<<"右括号不可能大于左括号!!!"<<endl;}if(IsOperator(exp[m+1])&&(exp[m+1]=='+'||exp[m+1]=='-'||exp[m+1]=='*'||exp[m+1]=='/'||exp[m+1]==')')){numofoperator++;m++;if(exp[m]==')')rb++;}else if(IsOperator(exp[m+1])||IsOperand(exp[m+1])){error++;cout<<"右括号后不可能直接跟数据或左括号!!!"<<endl;}     }else if(check=='('){lb++;if(IsOperator(exp[m+1])&&exp[m+1]=='('||exp[m+1]=='-')//左括号右边只能是数字或者"-"号{m++;m++;lb++;}else if(IsOperator(exp[m+1])){error++;cout<<"左括号后运算符只能跟左括号!!!"<<endl;}}else{     numofoperator++;if(IsOperator(exp[m+1])&&exp[m+1]=='('){m++;lb++;}else if(IsOperator(exp[m+1])){error++;cout<<"非括号的运算符不能直接接非括号运算符!!!"<<endl;}}}else{error++;cout<<check<<"为非法字符!!!"<<endl;}}if((error==0)&&(lb==rb)&&(numofoperand!=0)&&(numofoperator!=0))return true;elsereturn false;
}
bool   addition(char   OperatorA,char   OperatorB)         //A和B的优先级相同时返回TRUE.
{   if(OperatorA==OperatorB||(OperatorA=='*'&&OperatorB=='/')||(OperatorA=='/'&&OperatorB=='*')||(OperatorA=='+'&&OperatorB=='-')||(OperatorA=='-'&&OperatorB=='+'))   return   true;   elsereturn   false;
}   bool TakesPrecedence(char OperatorA,char OperatorB)  //按照优先级用if从最优至最后从上至下排列,从而达到比较A与B的优先级
{if(OperatorA=='(')return false;else if(OperatorB=='(')return false;else if(OperatorB==')')return true;else   if(addition(OperatorA,OperatorB))  return false;else if((OperatorA=='*')||(OperatorA=='/'))return true;else if((OperatorB=='*')||(OperatorB=='/'))return false;else   if((OperatorA=='+')||(OperatorA=='-'))   return   true;elsereturn true;
}//****************************************************************************//class BinNode{public:string data;BinNode *left_child;BinNode *right_child;BinNode(string k)    //构造函数{data=k;left_child=NULL;right_child=NULL;}
};class binarytree//树的类
{public:BinNode *root;         //根节点binarytree(void){root=NULL;}   //构造函数void print(void){print(root);}void print(BinNode *p){if(p!=NULL){print(p->left_child);print(p->right_child);cout<<p->data<<" ";}}void evaluate(void){evaluate(root);}bool evaluate(BinNode *prt)  //计算二叉树一个节点{if(IsOperator(prt->data)&&!IsOperator(prt->left_child->data)&&!IsOperator(prt->right_child->data))//计算二叉树结点的值并存入新的二叉树结点{float num=0;float num1=atof(prt->left_child->data.c_str());float num2=atof(prt->right_child->data.c_str());if(prt->data=="+")num=num1+num2;else if(prt->data=="-")num=num1-num2;else if(prt->data=="*")num=num1*num2;else if(prt->data=="/"){if(num2==0.0){cout<<"除数为零!!!运算出错";return 0;}elsenum=num1/num2;}stringstream bob;bob<<num;string suzzy(bob.str());prt->data=suzzy;prt->left_child=NULL;prt->right_child=NULL;}else if(prt->left_child==NULL&&prt->right_child==NULL);else{evaluate(prt->left_child);evaluate(prt->right_child);evaluate(prt);}return 1;}void clear_help(void){clear_help(root);}void clear_help(BinNode *rt){if(rt!=NULL){clear_help(rt->left_child);clear_help(rt->right_child);delete rt;}}
};BinNode *build_node(string x)//创建一个临时结点
{BinNode *new_node;new_node=new BinNode(x);return (new_node);
}void copy(BinNode *&r1,BinNode* r2)//这里将单个的子树连接起来
{if(r2==NULL)r1=NULL;else{r1=build_node(r2->data);copy(r1->left_child,r2->left_child);copy(r1->right_child,r2->right_child);}
}
//*******************************************************************************************int main()
{binarytree etree;//创建树stack<binarytree> NodeStack;//创建栈stack<char> OpStack;string exp;//声明字符串char choice='y';//choice为选择是否继续运行程序的判断char c;//为下面创建二叉树进行取字符while(choice=='y'||choice=='Y'){cout<<"请输入一个有效的表达式:"<<endl;getline(cin,exp);cout<<"     "<<endl<<"-----------------------------"<<endl;if(judge(exp))//如果判断出表达式没有错误,则进行创建二叉树并计算{cout<<"表达式格式正确"<<endl;for(int i=0;i<exp.size();i++){c=exp[i];if(i==0 && c=='-') //若开始为负,则把零压入运算数栈,把'-'压入运算符栈{   binarytree   temp;   temp.root=build_node("0");  NodeStack.push(temp);OpStack.push('-');}elseif(IsOperand(c))//若是操作数,则判断下一位是不是操作数,并且将整个数据创建一个子树并压栈{string tempstring="";tempstring=tempstring+c;while(i+1<exp.size()&&IsOperand(exp[i+1]))   //当当前位置的下一位也是操作数时,将整个数字放在一个临时数据串中{   tempstring+=exp[++i];   }binarytree temp;//为这个数据创建一个子树temp.root=build_node(tempstring);NodeStack.push(temp);//将子树的根节点指针压栈}else if(c=='+'||c=='-'||c=='/'||c=='*')//如果是操作符{if(OpStack.empty())//如果栈空,则直接压栈OpStack.push(c);else if(OpStack.top()=='(')//如果栈顶是左括号,则压栈OpStack.push(c);else if(TakesPrecedence(c,OpStack.top()))//判断栈顶字符和当前字符的优先级,当c优先级高或者个优先级相同时,将c压栈OpStack.push(c);else//其他普通情况{   while(!OpStack.empty()&&(TakesPrecedence(OpStack.top(),c)||addition(OpStack.top(),c)))//这里将在一般情况下,对已经压栈的操作数和操作符进行创建子树处理,并将当前字符压栈{binarytree temp_tree;string thisstring="";thisstring=thisstring+OpStack.top();//取栈顶进行计算字符串OpStack.pop();etree.root=build_node(thisstring);//当前树的根为栈顶计算出的字符串copy(temp_tree.root,NodeStack.top().root);//子树的根节点放在临时树结点上NodeStack.pop();etree.root->right_child=temp_tree.root;//将临时结点放入新建子树的右孩子结点上,可以将个子树连接起来temp_tree.root=NULL;//置空临时树结点copy(temp_tree.root,NodeStack.top().root);//重复上面的步骤连接左孩子etree.root->left_child=temp_tree.root;NodeStack.pop();temp_tree.root=NULL;copy(temp_tree.root,etree.root);NodeStack.push(temp_tree);etree.root=NULL;}OpStack.push(c);}}else if(c=='(')    //若中间遇到括号,则判断下一位是否为'-'{OpStack.push(c);if(exp[i+1]=='-'){binarytree   temp;temp.root=build_node("0");NodeStack.push(temp);OpStack.push('-');i++;}}   else if(c==')')//如果遇到右括号,则创建子树,直到与左括号匹配成功,这里和前一步骤的操作基本相同{while(OpStack.top()!='('){binarytree temp_tree;string thisstring="";thisstring=thisstring+OpStack.top();OpStack.pop();etree.root=build_node(thisstring);copy(temp_tree.root,NodeStack.top().root);NodeStack.pop();etree.root->right_child=temp_tree.root;temp_tree.root=NULL;copy(temp_tree.root,NodeStack.top().root);etree.root->left_child=temp_tree.root;NodeStack.pop();temp_tree.root=NULL;copy(temp_tree.root,etree.root);NodeStack.push(temp_tree);   etree.root=NULL;}OpStack.pop();}}while(!OpStack.empty())//如果栈非空,则继续进行出栈、判断、计算,直到栈空,栈中的结果为最终的计算结果{binarytree temp_tree;string thisstring="";thisstring=thisstring+OpStack.top();OpStack.pop();etree.root=build_node(thisstring);copy(temp_tree.root,NodeStack.top().root);NodeStack.pop();etree.root->right_child=temp_tree.root;temp_tree.root=NULL;copy(temp_tree.root,NodeStack.top().root);etree.root->left_child=temp_tree.root;NodeStack.pop();temp_tree.root=NULL;copy(temp_tree.root,etree.root);NodeStack.push(temp_tree);if(!OpStack.empty())etree.root=NULL;}//cout<<"Postfix traversal:";//etree.print();//cout<<endl;etree.evaluate();cout<<"表达式计算结果:"<<exp<<"="<<etree.root->data<<endl;cout<<"------------------------------------------------"<<endl;cout<<endl<<"是否继续计算下一个表达式<y/n>:";cin>>choice;getchar();}else{cout<<"**************************"<<endl;cout<<"错误:表达式有误"<<endl;cout<<endl<<"是否继续计算下一个表达式<y/n>:";cin>>choice;getchar();}}return 0;
}

二叉树思想实现的计算器相关推荐

  1. java编写计算类加减乘除_老师要求张浩使用面向对象的思想编写一个计算器类(Calculator),可以实现两个整数的加减乘除的运算.java...

    导航:网站首页 > 老师要求张浩使用面向对象的思想编写一个计算器类(Calculator),可以实现两个整数的加减乘除的运算.java 时间:2019-4-10 老师要求张浩使用面向对象的思想编 ...

  2. java calculator类_java里使用面向对象的思想编写一个计算器类(Calculator),可以实现两个数的加、减、乘、除运算...

    展开全部 package calculate; import java.math.BigDecimal; import java.math.BigInteger; import java.util.r ...

  3. 二叉树算法大总结:借助遍历的题型+需要借助递归返回多个信息的题型[本质:遍历]

    需要借助遍历的题型 题目一:翻转二叉树 思路:前中后序都可以 注意:中序遍历特别注意:在遍历左子树的时候,是传root.left的,因为,你上一步交换了左右指针,看代码一下就明白了 代码: /*** ...

  4. 二叉树的深度(递归+非递归)

    递归实现基本思想: 为了求得树的深度,可以先求左右子树的深度,取二者较大者加1即是树的深度,递归返回的条件是若节点为空,返回0 算法: int FindTreeDeep(BinTree BT){int ...

  5. 数据结构(二叉树相关、满、完全二叉树、霍夫曼树、排序方法及时间复杂度总结、)笔记-day11

    目录 前言 一.树(Tree) 1.1树及特征 1.2二叉树概念及性质 1.3二叉树存储结构及遍历 1.4链式存储编码 二.霍夫曼树(最优二叉树) 2.1权值及带权路径长度 2.2霍夫曼树特征及构建 ...

  6. 【数据结构Note5】- 树和二叉树(知识点超细大全-涵盖常见算法 排序二叉树 线索二叉树 平衡二叉树 哈夫曼树)

    文章目录 5.1 树和二叉树引入 5.1.1 树的概念 5.1.2 树的表示 5.1.3 树中基本术语 5.2 二叉树 5.2.1 概念 5.2.2 二叉树的性质 5.2.3 特殊的二叉树 5.2.4 ...

  7. GUI编程,简易计算器的实现

    这次的小练习分享,需要完成这样的一个简单的要计算器,如图: 当点击 等号 的按钮时,第三个文本框中的参数 需要显示为 第一个文本框和第二个文本框当中的参数 计算后的和,并且需要清空第一个和第二个文本框 ...

  8. java科学计算器报告心得,Java计算器课程设计报告---模拟科学计算器

    Java计算器课程设计报告---模拟科学计算器 高级编程技术课程设计高级编程技术课程设计 模拟科学计算器模拟科学计算器 一一.概述概述 1.程序程序具备的功能具备的功能 (1)使用图形用户界面一个文本 ...

  9. Kdtree(K-dimension tree)学习

    以下总结纯属个人学习理解,如有不对还望留言改正.参考文章博客地址如下: https://blog.csdn.net/likika2012/article/details/39619687 https: ...

最新文章

  1. JQuery实现一个简单的鼠标跟随提示效果
  2. WPF异步载入图片,附带载入中动画
  3. Ruby on Rails 實戰聖經阅读(三)
  4. 硬盘序列号查询软件_【西数硬盘购买指南】干货——西数移动硬从购买到验证体会心得...
  5. IO流——字节流的使用
  6. B站回应视频监控被破解上传:下架相关内容 封禁账号
  7. Qt4_Shreadsheet电子表应用
  8. hfss仿真软件入门教程
  9. macOS Command - xcode-select
  10. 最近服务器总被webshell攻击,木马也非常猖獗
  11. 请问如何制作中国象棋对弈软件的界面部分?
  12. Winform中HelpButton的用法总结
  13. PLG SaaS 产品 Figma 商业模式拆解
  14. 装机大师无法发现linux硬盘,如何解决PE无法识别硬盘的问题
  15. 智能家居系统模型设计2.0
  16. GBA程序开发入门3
  17. 如何安装谷歌服务框架?(Google三件套下载教程)
  18. 最大期望(EM)算法
  19. 艺龙私有化,携程与腾讯眉来眼去
  20. C练题笔记之:Leetcode-662. 二叉树最大宽度

热门文章

  1. Delete `␍`eslint(prettier/prettier) 错误的解决方案
  2. 数据结构------顺序结构
  3. 对数坐标归一化_归一化方法 Normalization Method
  4. Devil May Cry 1 台词及翻译
  5. 解决用 posman 调用 openai API 正常,用java代码调用超时问题
  6. x32dbg、x64dbg逆向微信发送信息
  7. matlab图像算子变换,拉布拉斯算子锐化图像的空域和频域--matlab实现
  8. 从开发者的角度剖析微信小程序
  9. arcgis pro发布bim模型
  10. SpringCloud 微服务工作笔记:validationQuery: SELECT 1 FROM DUAL