建立二叉树的表达式并求值

建立二叉树的表达式并求值

数据结构的一次作业,本来对c递归的知识了解的不是特别透彻,经此一役又有了新的理解

  • 测试数据

2.2*(3.1+1.20)-7.5/3

  • 二叉树的建立
    如下图所示:
    在这里插入图片描述
  • 代码如下
#include <iostream>
#include<stdlib.h>
#include<stack>
#include<algorithm>
#include<string.h>
#include<cmath>
using namespace std;
typedef struct BiTNode{
	union data{
		char ch;
		float e;
	}data;
	struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
int n=0;//叶子个数
int sum=0;//运算符个数
int deep=0;//深度
struct HString{
	char *elem;
	int length;
};
void initsq(struct HString &p){
	p.elem=(char*)(malloc(sizeof(struct HString)*100));
	p.length=0;
}
void InitBiTree(BiTree &T) //初始化二叉树T 
{
	T=(BiTree)malloc(sizeof(BiTNode));
	if(!T)exit(1);	
} 
 
//首个为字符串#数中数据的个数 
BiTNode* createTree(HString &L,int frist,int last) //还要考虑小括号在最外层的情况
{
	BiTree T1;
	int flag=0;//判定是否存在叶子结点(叶子结点均为数字)
	for(int i=frist;i<last;i++){
		if(L.elem[i]=='+'||L.elem[i]=='-'||L.elem[i]=='*'||L.elem[i]=='/'){
			flag=1;
			break;
		}
	} 
	if(!flag)
	{
		BiTree Ty;
	 	InitBiTree(Ty);
	 	char temp[10];
	 	int index=0;
	 	memset(temp,'\n',sizeof(temp));
	 	for(int i=frist;i<last;i++)
	 		temp[index++]=L.elem[i];
		Ty->data.e=atof(temp);
		deep++;
		n++;
		Ty->lchild=NULL;
		Ty->rchild=NULL;
		return Ty;
	}	
	flag=0;
	int jt=0,ct=0,t=0;
	for(int i=frist;i<last;i++)
	{
		if(L.elem[i]=='(')flag++;
		else if(L.elem[i]==')')flag--;
		//1+2*7-7.5/3
		if(flag==0){
            if(L.elem[i]=='+'||L.elem[i]=='-')
				jt=i;
			else if(L.elem[i]=='*'||L.elem[i]=='/')
				ct=i;
		}
	}
	if(flag!=0){
		printf("input error\n");
		exit(1);
	}
	if((ct==0)&&(jt==0))
		T1=createTree(L,frist+1,last-1); 
	else{
		if(jt>0)t=jt;
		else if(ct>0)t=ct;
	InitBiTree(T1);
	if(L.elem[t-1]=='+'||L.elem[t-1]=='-'||L.elem[t-1]=='*'||L.elem[t-1]=='/'){
		printf("input error\n");
		exit(1);
	}
	if(L.elem[t+1]=='+'||L.elem[t+1]=='-'||L.elem[t+1]=='*'||L.elem[t+1]=='/')
	T1->data.ch=L.elem[t];
	deep++;
	int count=deep;
	T1->lchild=createTree(L,frist,t);
	int lcount=deep;
	deep=count;
	T1->rchild=createTree(L,t+1,last);
	if(lcount>deep)
		deep=lcount;
	}
	return T1;
}
void calculate(BiTree T,stack<float> &S)
{
	if(T==NULL)
	{
		return;
	}
	else
	{	
		calculate(T->lchild,S);
		calculate(T->rchild,S);
		if(T->data.ch!='+'&&T->data.ch!='-'&&T->data.ch!='/'&&T->data.ch!='*')
		{
			float n=T->data.e;
			S.push(n);
		}
		else
		{	float a=S.top();
			S.pop();
			float b=S.top();
			S.pop();
			float result=0;
			if(T->data.ch=='+')result=b+a;
			else if(T->data.ch=='-')result=b-a;
			else if(T->data.ch=='/')result=b/a;
			else if(T->data.ch=='*')result=b*a;
			S.push(result);	
		}	
	}	
}
int main(int argc, char** argv) {

	BiTNode *T;
	struct HString L;
	initsq(L);
	printf("Tips:括号是英文格式\n");
	while(scanf("%c",&L.elem[L.length++])&&L.elem[L.length-1]!='\n');
	L.length--;
	T=createTree(L,0,L.length);
	stack<float>S;
	calculate(T,S);
	printf("\n叶子节点数:%d      深度:%d\n\n%.2f",n,(int)(log(n+sum)/log(2))+1,S.top());
	return 0;
}

这里的代码大部分参照了其他人的,自己增加了一些功能:

  • 判断错误输入
    • 四则运算符是否冗余输入
      解决办法:
      有上述的二叉树可知,运算符不可能是叶子结点,因此在将叶子结 点添加到树上时,可以先对其前后的数据进行判断,若还是运算符则退出程序
    • 括号是否能够匹配
      解决办法:
      设置flag在遍历输入的数据时遇到(则加一,遇到)则减一
      最后判断flag是否为0,即可
  • 增加了对小数的运算
    在添加叶子结点即运算数时,总是存在着first指向数据,last指向一个运算符,且(first,last)之间不存在数据,因此可在区间内遍历是否存在运算符,若没有就将其添加到树上
  • 实现了求深度的操作
  • 实现了求叶子数量的求解
    参考的博客https://blog.csdn.net/zj19941201/article/details/72833138

猜你喜欢

转载自blog.csdn.net/qq_40933929/article/details/84890971