1. 程式人生 > >建立二叉樹的表示式並求值

建立二叉樹的表示式並求值

建立二叉樹的表示式並求值

資料結構的一次作業,本來對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