建立二叉树的表达式并求值
数据结构的一次作业,本来对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