建立二叉樹的表示式並求值
阿新 • • 發佈:2018-12-08
建立二叉樹的表示式並求值
資料結構的一次作業,本來對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