数据结构实验二——二叉树的遍历和计算

《数据结构》实验二报告

一、目的和要求(需求分析):

1、掌握二叉树的存储结构以及二叉树的建立和操作。

2、输入一串表达式后,建立二叉树,并对其进行先序、中序和后序的遍历。
(输入表达式如此形式:a+b*c-d-e/f….;)

3、递归实现表达式运算。

二、程序设计的基本思想,原理和算法描述:

1.程序的结构:使用二叉树存储输入的表达式,其中叶子节点存储操作数,而其余节点存储运算符,不同层级的运算符则代表运算的先后顺序。

2.输入/输出设计:直接从键盘读入若干字符串形式的表达式,以string类型存入,而后利用tofloat()函数将数字部分转化成float类型。

3.计算的基本原理:利用二叉树存储的特性,利用乘除运算优先加减方式,先构建加减节点,然后构建乘除,最后将所有数字填入叶子节点。而计算时候直接从叶子节点读出两个数字根据双亲节点进行运算即可。

4.遍历的基本原理:通过调整对自身节点的和对左右子节点访问的顺序和递归调用就可以很容易实现二叉树的前中后序遍历。

三、调试和运行程序过程中产生的问题及采取的措施:

1.一开始对于string转化数字使用的是int类型,但是明显对于/运算会损失精度,所以后来装换成float,而改代码中由于忘记修改函数的返回值为float,所以浪费了很多时间debug。

2.一开始对于多位数字没有一个很好的办法处理,后来查到可以利用字符减去’0’后再强转成float形式最后乘以位数相应的10次方形式进行。

四、代码演示

#include<bits/stdc++.h>
using namespace std;
using EleType=string; 
struct Tree{
	EleType data;
	Tree* left=NULL;
	Tree* right=NULL;
};  
Tree* root=NULL;

float tofloat(string s){//string to float
	float sum=0.0;
	int t=1;
	for(int i=s.length()-1;i>=0;i--){
		sum+=(s[i]-'0')*t*1.0;
		
		t*=10;
	}
	return sum;
}

float calculate(Tree* p){//计算 
	if(p->data!="+"&&p->data!="-"&&p->data!="*"&&p->data!="/"){
		return tofloat(p->data);	
	} 
	if(p->data=="+"){
		return calculate(p->left)+calculate(p->right);
	}
	if(p->data=="-"){
		return calculate(p->left)-calculate(p->right);
	}
	if(p->data=="*"){
		return calculate(p->left)*calculate(p->right);
	}
	if(p->data=="/"){
		return calculate(p->left)/calculate(p->right);
	}
}

Tree* Build(string s,int l,int r){ //建树 
	
	int rt=-1;
	
	if(l>r){
		return NULL;
	}
	
	//寻找根节点 
	for(int i=r;i>=l;i--){
		if(s[i]=='+'||s[i]=='-'){
			rt=i;
			break;
		}

	}
	if(rt==-1){
		for(int i=r;i>=l;i--){
			if(s[i]=='*'||s[i]=='/'){
				rt=i;
				break;
			}
		}	
	}
	
	//无根节点,建立叶子节点 
	if(rt==-1){
		Tree* p=new Tree;
		p->data=string(s,l,r-l+1);
	return p;
	}
	//递归建树 
	Tree* p=new Tree;
	p->data=string(s,rt,1);
	p->left=Build(s,l,rt-1);
	p->right=Build(s,rt+1,r);
	return p;	
}
void PreTra(Tree* p){//先序遍历 
	if(p==NULL) return;
	cout<<p->data<<" ";
	PreTra(p->left);
	PreTra(p->right);
	return;
}

void MidTra(Tree* p){//中序遍历 
	if(p==NULL) return;
	MidTra(p->left);
	cout<<p->data<<" ";
	MidTra(p->right);
	return;
}

void PosTra(Tree* p){//后序遍历 
	if(p==NULL) return;
	PosTra(p->left);
	PosTra(p->right);
	cout<<p->data<<" ";
	return;
}

void tra(Tree *root){
	cout<<"前序遍历:"; 
	PreTra(root);
	cout<<endl;
	cout<<"中序遍历:"; 
	MidTra(root);
	cout<<endl;
	cout<<"后序遍历:"; 
	PosTra(root);
	cout<<endl;
} 

void Test(){
	
	//输入只含数字以及+-*/的字符串 
	string s;
	cin>>s;
	root=Build(s,0,s.length()-1);
	cout<<calculate(root)<<endl;
	tra(root);
	
}

int main(){
	
	Test();
	return 0;
	
}

在这里插入图片描述

五、心得与体会:

1、掌握二叉树的存储结构以及二叉树的建立和操作。
2、输入一串表达式后,建立二叉树,并对其进行先序、中序和后序的遍历。
3、递归实现表达式运算。
4、因为在建立二叉树的时候就根据加减乘除的运算先后分出树层级结构,所以后期计算的时候可以不用考虑运算的优先级问题,直接将叶子节点的数字节后双亲节点的运算符进行运算即可。
5、学到了处理字符串多位数字转化成数字的方法。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值