表達式樹
阿新 • • 發佈:2018-09-09
root 葉子 處理 head continue calc header 表達 方便
1. 筆記
表達式樹是一種存儲和計算表達式的方式。表達式樹的葉子結點均為數,非葉子結點均為運算符。我自己摸索了一下用表達式樹處理表達式,確實很直觀方便。下面的代碼可以處理+,-,*,/,%,^六種左結合的二元運算,優先級為:
運算符 | 優先級 |
---|---|
+,- | 3 |
*,/,% | 2 |
^ | 1 |
其它 | 0 |
2. 代碼
/* 備註: 未嚴格測試,可能有bug 2018/09/09 */ #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) #define ms(arr,a) memset(arr,a,sizeof arr) #define debug(x) cout<<"< "#x" = "<<x<<" >"<<endl int pri[300]; void init_pri() { pri[‘+‘]=pri[‘-‘]=3; pri[‘*‘]=pri[‘/‘]=pri[‘%‘]=2; pri[‘^‘]=1; } struct node { double v; char c; node *fa,*l,*r; node(){c=v=0;fa=l=r=NULL;} node(double x){v=x;c=0;fa=l=r=NULL;} node(char x){v=0;c=x;fa=l=r=NULL;} }; void recycle(node *root) { if(root==NULL)return; recycle(root->l);recycle(root->r); delete root; } const int maxn=1e3; char s[maxn]; const double eps=1e-10; inline bool is_num(char *i) { return ((*i)>=‘0‘&&(*i)<=‘9‘)||(*i)==‘.‘; } double get_num(char *&i) { bool is_f=false;double it=0.1; double ret=0; for(;is_num(i);++i) { if((*i)==‘.‘){is_f=true;continue;} if(is_f) { ret=ret+((*i)-‘0‘)*it; it=it/10; }else ret=ret*10+(*i)-‘0‘; } i--; return ret; } double calc(node *root) { if(root->c==0)return root->v; double lft=calc(root->l),rgt=calc(root->r); switch(root->c) { case ‘+‘: return lft+rgt; break; case ‘-‘: return lft-rgt; break; case ‘*‘: return lft*rgt; break; case ‘/‘: return lft/rgt; break; case ‘%‘: return int(lft)%int(rgt); break; case ‘^‘: return pow(lft,rgt); break; } } node* construct(char *l,char *r) { node *pos=NULL,*nxt,*root; for(char *i=l;i<=r;++i) { //構造新結點 if((*i)==‘(‘) { char *lft=i+1; int cnt=1; while(cnt) { i++; if((*i)==‘(‘)cnt++; if((*i)==‘)‘)cnt--; } nxt=construct(lft,i-1); double tmp=calc(nxt); recycle(nxt); nxt=new node(tmp); } else if(is_num(i))nxt=new node(get_num(i)); else nxt=new node((*i)); //插入新結點 node *a=pos,*b=NULL; pos=nxt; if(a==NULL){root=nxt;continue;} while(a&&pri[a->c]<=pri[nxt->c]){b=a;a=a->fa;} if(a==NULL){root=nxt;nxt->l=b;b->fa=nxt;continue;} if(b==NULL){a->r=nxt;nxt->fa=a;continue;} if(b==a->l)a->l=nxt; else a->r=nxt; nxt->fa=a;nxt->l=b;b->fa=nxt; } return root; } int main() { init_pri(); printf(">"); while(~scanf("%s",s)) { node *root=construct(s,s+strlen(s)-1); double ans=calc(root); long long nans=(long long)ans; if((ans-nans<eps)&&(ans-nans>-eps))printf("%lld",nans); else printf("%.6f",ans); printf("\n\n>"); recycle(root); } }
表達式樹