表达式树
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);}
}
轉載于:https://www.cnblogs.com/maoruimas/p/9611336.html
總結
- 上一篇: 以理开头的成语有哪些啊?
- 下一篇: JQ实现当前页面导航加效果(栏目页有效)