二叉树实现四则运算计算器(含源码演示和详细说明)
说明:禁止转载,对源码的要求是禁止把这个东西原封不动或非常小量改动后用于课程设计(我很建议你自己动手实现,你会做的比我更好),源码仅供学习参考,思路仅供参考,仍有不足,欢迎评论指出。
1.问题定义及需求分析
二叉树算术表达式求值,设计十进制整数四则运算计算器。
1)采用二叉树等存储结构。
2)给定表达式字符串,生成二叉树。
3)对二叉树遍历求值并输出。
2.概要设计
通过宏定义预先定义可输入的最大长度maxsize。用一个结构体BtreeNode代表二叉树的节点。
通过afaToBtree函数将输入的字符串转化成二叉树,然后通过cal函数将所生成的二叉树进行遍历,从而计算出最终结果。
3.详细设计
结构体的设计:
因为二叉树的节点既有可能存放运算符,有有可能存放数字,因此在定义结构体时,除了左右孩子,又定义的存放数字的double型变量data和存放运算符的char型变量yunsuan。
typedef struct BtreeNode{
double data;//数字型节点
char yunsuan;//运算符型节点
struct BtreeNode *lchild;
struct BtreeNode *rchild;
}BtreeNode;
生成二叉树的设计:创建函数afaToBtree,输入字符串,起点s和终点e。若改字符串全为数字组成,则计算出所对应的数字,将其存储在data中。若不全为数字,则寻找优先级最低的运算符,既括号外且最右侧的+-或*/符号(都有则取+-),将其作为根节点,将改节点左侧和右侧的内容作为左右孩子,重复调用函数,通过不断调用函数,生成叶子节点均为数字的二叉树。
BtreeNode* afaToBtree(char *input,int s,int e)
{
int local_r=0,flag=0,i;
int m_m_p=0,a_s_p=0,x=0,xishu;
for(i=s;i<e;i++)
if(input[i]=='+'||input[i]=='-'||input[i]=='*'||input[i]=='/')
x++;//判断是否全为数字,如果是x取零
if(!x)
{
int y;
y=input[e-1]-'0';
for(i=e-2,xishu=1;i>=s;i--)
{
xishu=10*xishu;
y=y+xishu*(input[i]-'0');
}//将该字符串所代表的数字算出
BtreeNode* bn=(struct BtreeNode*)malloc(sizeof(struct BtreeNode));
bn->data=y;
bn->yunsuan=NULL;
bn->lchild=NULL;
bn->rchild=NULL;
return bn;//将该数字的值返回给节点的data中
}
for(i=s;i<e;i++)
{
if(input[i]=='(')
flag++;
else if(input[i]==')')
flag--;//判断该字符是否在括号内,在内flag为1,在外为0
if(!flag)
{
if(input[i]=='*'||input[i]=='/')
m_m_p=i;//将括号外的最右侧的*或/号的位置记录下来
else if(input[i]=='+'||input[i]=='-')
a_s_p=i;//将括号外的最右侧的+或-号的位置记录下来
}
}
if((m_m_p==0)&&(a_s_p==0))
afaToBtree(input,s+1,e-1);//去掉最外层的括号
else
{
if(a_s_p>0)
local_r=a_s_p;
else if(m_m_p>0)
local_r=m_m_p;//将记录下的+-或*/号记录下来,作为根节点
BtreeNode* b=(struct BtreeNode*)malloc(sizeof(struct BtreeNode));
b->yunsuan=input[local_r];
b->lchild=afaToBtree(input,s,local_r);
b->rchild=afaToBtree(input,local_r+1,e);//对该根节点的左侧和右侧分别再次操作
return b;
}
}
遍历二叉树求值的设计:通过double型函数cal,输入二叉树的根节点,从该根节点出发,若为数字则直接返回给函数,若为运算符则判断为加减乘除,并对该节点两端的式子进行相应的运算,若两端仍为表达式则继续调用该函数,直至全为数字,并计算出结果。
double cal(BtreeNode *root){
switch(root->yunsuan){
case '+':{
return cal(root->lchild)+cal(root->rchild);
break;
}
case '-':{
return cal(root->lchild)-cal(root->rchild);
break;
}
case '/':{
return cal(root->lchild)/cal(root->rchild);
break;
}
case '*':{
return cal(root->lchild)*cal(root->rchild);
break;
}//通过对根节点的运算符的遍历,判断加减乘除并进行操作,最后将结果返回
}
return root->data;
}
4.调试分析:
在测试中,发现了输出结果一直为0的问题,后发现将double型数据当作int型用%d输出了,将其改为%lf后恢复正常。后在测试中发现了计算结果与实际结果不符的问题,经验证,是根节点的右孩子的计算出现了问题。通过不断的排查,发现在红字体i=s处,写成了i=0,从而导致无论s是几,都会从i=0开始遍历,因此对左指数无影响,而对右子树有影响,因为s不再是0,从而导致计算结果错误。在改正该错误后,问题得到解决,计算结果正确。
for(i=s;i<e;i++)
if(input[i]=='+'||input[i]=='-'||input[i]=='*'||input[i]=='/')
x++;//判断是否全为数字,如果是x取零
if(!x)
{
int y;
y=input[e-1]-'0';
for(i=e-2,xishu=1;i>=s;i--)
{
xishu=10*xishu;
y=y+xishu*(input[i]-'0');
}//将该字符串所代表的数字算出
5.使用说明
调整最大输入长度,可以通过修改宏定义来实现。如设置最大长度为100,则输入
#define maxsize 100
输入时可输入数字及+-*/符号,优先计算的可用()括起来,计算顺序与我们日常的计算顺序一致。如输入:12+(21-4)/3+(3+2)*14
6.测试结果
7.附录
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxsize 100//可输入的最大长度
typedef struct BtreeNode{
double data;//数字型节点
char yunsuan;//运算符型节点
struct BtreeNode *lchild;
struct BtreeNode *rchild;
}BtreeNode;
BtreeNode* afaToBtree(char *input,int s,int e)
{
int local_r=0,flag=0,i;
int m_m_p=0,a_s_p=0,x=0,xishu;
for(i=s;i<e;i++)
if(input[i]=='+'||input[i]=='-'||input[i]=='*'||input[i]=='/')
x++;//判断是否全为数字,如果是x取零
if(!x)
{
int y;
y=input[e-1]-'0';
for(i=e-2,xishu=1;i>=s;i--)
{
xishu=10*xishu;
y=y+xishu*(input[i]-'0');
}//将该字符串所代表的数字算出
BtreeNode* bn=(struct BtreeNode*)malloc(sizeof(struct BtreeNode));
bn->data=y;
bn->yunsuan=NULL;
bn->lchild=NULL;
bn->rchild=NULL;
return bn;//将该数字的值返回给节点的data中
}
for(i=s;i<e;i++)
{
if(input[i]=='(')
flag++;
else if(input[i]==')')
flag--;//判断该字符是否在括号内,在内flag为1,在外为0
if(!flag)
{
if(input[i]=='*'||input[i]=='/')
m_m_p=i;//将括号外的最右侧的*或/号的位置记录下来
else if(input[i]=='+'||input[i]=='-')
a_s_p=i;//将括号外的最右侧的+或-号的位置记录下来
}
}
if((m_m_p==0)&&(a_s_p==0))
afaToBtree(input,s+1,e-1);//去掉最外层的括号
else
{
if(a_s_p>0)
local_r=a_s_p;
else if(m_m_p>0)
local_r=m_m_p;//将记录下的+-或*/号记录下来,作为根节点
BtreeNode* b=(struct BtreeNode*)malloc(sizeof(struct BtreeNode));
b->yunsuan=input[local_r];
b->lchild=afaToBtree(input,s,local_r);
b->rchild=afaToBtree(input,local_r+1,e);//对该根节点的左侧和右侧分别再次操作
return b;
}
}
double cal(BtreeNode *root){
switch(root->yunsuan){
case '+':{
return cal(root->lchild)+cal(root->rchild);
break;
}
case '-':{
return cal(root->lchild)-cal(root->rchild);
break;
}
case '/':{
return cal(root->lchild)/cal(root->rchild);
break;
}
case '*':{
return cal(root->lchild)*cal(root->rchild);
break;
}//通过对根节点的运算符的遍历,判断加减乘除并进行操作,最后将结果返回
}
return root->data;
}
int main()
{
char input[maxsize-1];//保存输入的字符串
int s=0,e;
double result;
printf("请输入需计算的表达式:");
scanf("%s",&input);//读入结果
e=strlen(input);//计算字符串的长度
result=cal(afaToBtree(input,s,e));//生成二叉树并计算出结果
printf("计算结果为%lf\n",result);//输出最终结果
}
二叉树实现四则运算计算器(含源码演示和详细说明)相关推荐
- 体验Android:个人所得税计算器 含源码
体验Android 个人所得税计算器 含源码 http://files.cnblogs.com/mobile/ptc.rar 转载于:https://www.cnblogs.com/mobile/ar ...
- php构建一个区块链(含源码)
php构建一个区块链(含源码) 我们要用PHP编程语言构建区块链,区块链本身就是一个非常简单的概念,它是一个非常简单的数据结构,数字货币是很复杂,但区块链不是,它们复杂的原因是共识算法,挖矿机制和运行 ...
- Markdown编辑器:纯前端演示(可接入项目、含源码下载) - 总结篇
可接入项目,提供全部代码下载. 通过本地html静态文件,演示效果. Editor.md是一款开源的.可嵌入的 Markdown 在线编辑器(组件),基于 CodeMirror.jQuery 和 Ma ...
- 老男孩GO语言线下培训班1期整套教程(完整18天含源码)
老男孩GO语言线下培训班1期整套教程(完整18天含源码) 老男孩教育-Go语言第一期(共18天 含课程源码) 课程详细目录: ├─L001-Go语言-mp4 │ 01 Go开发1期 day1 ...
- Hyperledger Fabric Rest API服务开发教程【含源码】
Hyperledger Fabric Rest API服务开发教程[含源码] Hyperledger Fabric 提供了软件开发包/SDK以帮助开发者访问fabric网络 和部署在网络上的链码,但是 ...
- Odoo16 教程含源码
Odoo16 教程含源码 Odoo16 开发教程 版本变化 模块开发步骤 源码 Odoo16 开发教程 Odoo 号称全球第一的开源ERP平台,除了提供一站式的企业应用开发解决方案,作为一个网站设计器 ...
- 超赞,20个炫酷的数据可视化大屏(含源码)
大家好,我是小F- 随着大数据的发展,可视化大屏在各行各业得到越来越广泛的应用. 可视化大屏不再只是电影里奇幻的画面,而是被实实在在地应用在政府.商业.金融.制造等各个行业的业务场景中,切切实实地实现 ...
- 一套免费Java开源农业物联网平台Version:3.0.1含源码
一套免费Java开源农业平台Version:3.0.1含源码 体验地址, V3 star star : 点我访问 体验地址, V2 star star : 点我访问 (没有广告)! 一.简介 一套免费 ...
- Qt数据库练习之QSqlTableModel的使用(MySql数据库示例,含源码+注释)
文章目录 一.操作示例 1.1 修改记录(数据) 1.2 添加记录(数据) 1.3 删除记录(数据) 1.4 取消操作 1.5 排序操作 1.6 查询操作 二.了解QSqlTableModel 三.源 ...
最新文章
- mysql 单列转换为行,mysql行转换为列
- 如果函数是可以遗传的
- 感謝有PPStream這種好東西
- brew报错:in `initialize‘: Version value must be a string; got a NilClass () (TypeError)
- 三、Java基础工具(1)_常用类——数学相关类
- 冒泡排序 c语言,冒泡排序(C语言)
- 深度学习笔记(一):logistic分类
- 架构思维成长系列教程(十)- 电商搜索引擎架构设计
- JAVA 进制转换工具
- Django之开发微信小程序后端-Django篇②
- 运行npm install 出现thon Python is not set from command line or npm configuration解决方案
- Sublime Text设置中文
- ThinkPHP V5.0.5漏洞_谷歌浏览器 v80.0.3987.100 正式版——墨涩网
- 操作系统学习笔记十二(基于分页的虚拟存储系统)
- STM32F103_study61_The punctual atoms(Clock System Intro)
- 一图看懂互联网各职位都是干啥的
- IJCAI 2021 投稿安排出来了!新审稿机制体验一下?
- “我转行做测试开发的这一年多,月薪5K变成了24K”,文科女生的自白
- 强大的头像制作神器_支持外卖CPS等优惠劵小程序源码
- 中国EMBA教育培训行业发展规划与投资规模预测报告2021年版