北京理工大学数据结构实验报告 简易计算器二叉树Word格式.docx
- 文档编号:15291408
- 上传时间:2022-10-29
- 格式:DOCX
- 页数:15
- 大小:66.36KB
北京理工大学数据结构实验报告 简易计算器二叉树Word格式.docx
《北京理工大学数据结构实验报告 简易计算器二叉树Word格式.docx》由会员分享,可在线阅读,更多相关《北京理工大学数据结构实验报告 简易计算器二叉树Word格式.docx(15页珍藏版)》请在冰豆网上搜索。
输入:
6+9-5输出:
10
b.乘除运算
5.6*2.7/2输出:
7.56
c.四则混合运算
(2+3)*8-3/2输出:
23.5
d.非法输入
(5+6(*5输出:
括号不匹配!
1.2问题分析
与之前利用栈实现计算器功能不同,本实验采取的方法是:
将中缀表达式转换成一棵二叉表达式树,通过对该树的后序遍历求出计算表达式的值。
所以,实验的重点是如何“将中缀表达式转换成一棵二叉表达式树”;
如上图所示,该二叉表达式树表示的是计算式(5+2)*3。
可以看出,操作数均为叶子结点,其它结点为操作符;
构建二叉树的整体思路是:
(1)将中缀表达式转化为后缀表达式;
(2)利用
(1)中的后缀表达式,在此基础上构建二叉表达式树。
最后的求值,可以通过递归调用函数,后序遍历二叉树来完成。
二、概要设计
2.1抽象数据类型定义
本程序主要用到的数据结构是二叉链表,所以先行定义链表结点,其中每一个节点包含两个数据域和两个指针域,数据域分别存放char型变量和float型变量,相对应是运算符和操作数;
指针域分别指向两个左右孩子。
structnode{
chardata;
floatnumber;
structnode*left;
structnode*right;
};
另外,考虑到程序还需转换后缀表达式,所以又建立了另一种结点类型变量,并定义其类型的数组array[20]:
structoprtnumber{
charsign;
//存放符号型变量
//存放浮点数
}array[20];
2.2主程序流程
主函数流程如下:
intmain()
{
char*b,a[100],*t;
b=convert();
//中缀表达式转为反序后缀表达式
do
{完成反序后缀式的逆向;
}
T=create(T,a);
//create()函数创建二叉链表
postordertraverse(T);
//后序遍历进行计算
输出结果;
}//main
2.3程序模块调用关系
具体关系如下图所示:
三、详细设计
3.1主函数的具体过程
intmain()
{structnode*T;
flag=0;
T=(structnode*)malloc(sizeof(structnode));
inti;
b=convert();
for(t=b;
*t!
='
\0'
;
t++);
i=0;
{t--;
a[i]=*t;
i++;
while(t!
=b);
a[i]='
//完成反序后缀式的逆向
postordertraverse(T);
printf("
%g"
result);
//输出结果
return0;
3.2其它函数的具体实现
char*convert();
//将运算式转换成逆后缀序列,并将该序列作为返回值;
首先输入运算式,判断是否为数字,将数字存入数组的数值域,并用符号代替数值,产生新的用符号表示的运算式。
然后用字符优先算法将算式转换为逆后缀式,将数组首地址传回给主函数。
并且在输入不合法时给予错误提示。
structnode*create(structnode*T,chard[]);
//建立二叉链表,并返回根结点
voidpostordertraverse(structnode*e);
//进行后序遍历,运用了递归的思想,实际上调用operation函数进行计算
floatoperation(floata,floatb,charc);
//四则运算函数,主要实现运算功能
intin(charc);
//判断是否为运算符,是运算符返回1
部分函数的代码如下:
(1)create函数
structnode*create(structnode*T,chard[])
{//建立二叉链表,并返回根结点
inti;
if(d[w]>
A'
&
d[w]<
Z'
)
{T->
data=d[w];
for(i=0;
array[i].sign!
i++)
{if(array[i].sign==d[w])
{T->
number=array[i].number;
break;
}
T->
left=NULL;
T->
right=NULL;
w++;
}
else{
if(flag==0)flag=1;
else
T=(structnode*)malloc(sizeof(structnode));
(T)->
w++;
left=(structnode*)malloc(sizeof(structnode));
right=(structnode*)malloc(sizeof(structnode));
right=create((T)->
right,d);
left=create((T)->
left,d);
}
returnT;
}//create
(2)operation函数
floatoperation(floata,floatb,charc)
{//四则运算函数,主要实现运算功能
switch(c){
case'
+'
:
returna+b;
-'
returna-b;
*'
returna*b;
/'
returna/b;
default:
运算符错误!
\n"
);
exit(0);
}}//operation
(3)in函数
intin(charc)
{//判断是否为运算符,是运算符返回1;
否则返回0
if(c=='
||c=='
('
)'
)
return1;
elsereturn0;
}//in
四、调试分析
4.1难点以及困难
1.由于本次试验做过堆栈式计算器,思维存在惯性,打不开新思路;
2.建立二叉链表是最重要的环节,而在这之前,必须先得到后缀表达式,由于之前没有接触过后缀表达式,从而给变成造成了困难。
即涉及char型和float型变量统一化,又有算符优先级的判别。
3.二叉链表的建立,要利用好优先级,以及注意操作数为叶子节点这一特点。
4.2经验与体会
1.算式计算的问题是一个非常经典的题目。
之前用栈来实现的。
但是用栈来实现是一个非常麻烦的过程,第一要解决算式判断,是否为符合规则的算式,第二要由中缀表达式转化为后缀表达式。
这两个部分是栈实现计算算式表达式的比较复杂的地方。
不仅如此,栈实现里面的各种运算符的优先级,各种条件判断,可以说是麻烦的要命。
相比之下,用二叉树免除了算式表达式的检查过程。
并不是不需要检查,而是检查的过程就包含在创建二叉树的过程。
认真分析,我们会发现,所有的叶子结点必须是操作数结点,而所有的非叶子结点必须是运算符结点,否则表达式的结构一点不正确,创建二叉树的过程就可以对表达式经行检查。
2.总结一句就是:
好的数据结构能事半功倍,要培养善于发现的思维,当有某个思路然后去实现它,另外要积累经验。
好好理解数据结构!
五、测试结果
1.加减运算
输入:
2.乘除运算
3.四则混合运算
4.非法输入
六、附录
#include<
stdio.h>
string.h>
stdlib.h>
math.h>
structnode{
structoprtnumber{
/*函数声明*/
char*convert();
//将运算式转换成逆后缀序列
structnode*create(structnode*T,chard[]);
//建立二叉链表
voidpostordertraverse(structnode*e);
//进行后序遍历
//四则运算函数
//判断是否为运算符,是运算符返回1
/*定义全局变量*/
intw,flag;
floatresult=0;
floatoperation(floata,floatb,charc)
{switch(c){
"
}}
structnode*create(structnode*T,chard[])
{inti;
data=d
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 北京理工大学数据结构实验报告 简易计算器二叉树 北京理工大学 数据结构 实验 报告 简易 计算器 二叉
![提示](https://static.bdocx.com/images/bang_tan.gif)