• 表达式求值


    注意:这是一篇个人学习笔记,如果有人因为某些原因点了进来并且要看一下,请一定谨慎地阅读,因为可能存在各种奇怪的错误,如果有人发现错误请指出谢谢!


    以前的:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 using namespace std;
     5 int lc[10000],rc[10000];
     6 int type[10000];
     7 double data[10000];
     8 char s[10000];
     9 int nc,len,p;
    10 bool judge_num(int x,int y)
    11 {
    12     if(y-x==1&&s[x]=='-')   return false;
    13     if(s[x]=='+'||s[x]=='*'||s[x]=='/'||s[x]=='^')
    14         return false;
    15     for(int i=x+1;i<y;i++)
    16     {
    17         if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/'||s[i]=='^')
    18             return false;
    19     }
    20     return true;
    21 }
    22 int build(int x,int y)
    23 {
    24     int i,c1=-1,c2=-1,c3=-1,p=0;
    25     int u;
    26     if(judge_num(x,y)==true)
    27     {
    28         u=++nc;
    29         lc[u]=rc[u]=0;
    30         type[u]=0;
    31         sscanf(s+x,"%lf",&data[u]);
    32         return u;
    33     }
    34     for(i=x;i<y;i++)
    35     {
    36         switch(s[i])
    37         {
    38             case '(': p++;break;
    39             case ')': p--;break;
    40             case '+': case '-': if(!p) c1=i;break;
    41             case '*': case '/': if(!p) c2=i;break;
    42             case '^': if(!p) c3=i;break;
    43         }
    44     }
    45     if(c1<0) c1=c2;
    46     if(c1<0) c1=c3;
    47     if(c1<0) return build(x+1,y-1);
    48     u=++nc;
    49     lc[u]=build(x,c1);
    50     rc[u]=build(c1+1,y);
    51     if(s[c1]=='+')  type[u]=1;
    52     else if(s[c1]=='-') type[u]=2;
    53     else if(s[c1]=='*') type[u]=3;
    54     else if(s[c1]=='/') type[u]=4;
    55     else type[u]=5;
    56     return u;
    57 }
    58 double run(int u)
    59 {
    60     if(type[u]==1)  return run(lc[u])+run(rc[u]);
    61     if(type[u]==2)  return run(lc[u])-run(rc[u]);
    62     if(type[u]==3)  return run(lc[u])*run(rc[u]);
    63     if(type[u]==4)  return run(lc[u])/run(rc[u]);
    64     if(type[u]==5)  return pow(run(lc[u]),run(rc[u]));
    65     return data[u];
    66 }
    67 int main()
    68 {
    69     scanf("%s",s+1);
    70     len=strlen(s+1);
    71     p=build(1,len+1);
    72     printf("%.3lf",run(p));
    73     return 0;
    74 }
    View Code

    写了个O(n)的表达式树...实际要用可能要稍微改一下

    题面:http://210.33.19.103/contest/997

    中缀转后缀自然是不用的...

    这里大部分的写法跟网上是一样的(就是两个栈:操作符栈,操作数栈;遇到数就加入数栈,遇到符号就while(栈顶操作符优先级>=当前的)不断弹出栈顶操作符(弹出方法:弹出操作符,以及两个栈顶操作数,做完运算后将结果放回操作数栈)),然而写的比较麻烦..写了一个"栈套栈",遇到左括号就新建一层栈,遇到右括号就做完当前层栈留下的运算符,将栈的层数减1,并把剩下的唯一一个数放入上一层栈

      1 //#pragma GCC optimize(3)
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<vector>
      6 using namespace std;
      7 #define fi first
      8 #define se second
      9 #define mp make_pair
     10 #define pb push_back
     11 typedef long long ll;
     12 typedef unsigned long long ull;
     13  
     14 int n,md;
     15 char ss[5001000];
     16  
     17 void do_ub(int x)
     18 {
     19     if(!x)
     20     {
     21         printf("failed:%d
    ",x);
     22         int *a=0;*a=234;
     23     }
     24 }
     25 #define assert(x) do_ub(x)
     26  
     27 struct Nd
     28 {
     29     int d;
     30     int type;//0:数字;1:+;2:-;3:*;4:/;5:(;6:)
     31     int num;
     32 };
     33 Nd pre[5001000];
     34 int inv[500100];
     35 int left,plen;
     36 int order[]={3,1,1,2,2};
     37 bool isdigit1(char x){return x>='0'&&x<='9';}
     38 int ma[666];
     39  
     40 int an[5001000];
     41 struct TNd
     42 {
     43     int ch[2];
     44     int type;
     45     int d,num;
     46 }nn[5001000];
     47 int mem;
     48 struct ST
     49 {
     50     int st1[10001000],st2[10001000],tp1,tp2;
     51     ST()
     52     {
     53         tp1=0;tp2=1;st2[1]=0;
     54     }
     55     void push(int x)
     56     {
     57         st1[++tp1]=x;
     58     }
     59     bool empty()
     60     {
     61         assert(tp1>=st2[tp2]);
     62         return tp1==st2[tp2];
     63     }
     64     void pop()
     65     {
     66         assert(tp1>st2[tp2]);
     67         if(tp1>st2[tp2]) --tp1;
     68     }
     69     int top()
     70     {
     71         assert(tp1>st2[tp2]);
     72         return st1[tp1];
     73         //return tp1>st2[tp2]?st1[tp1]:0;
     74     }
     75     void add_stack()
     76     {
     77         st2[++tp2]=tp1;
     78     }
     79     void del_stack()
     80     {
     81         assert(tp1==st2[tp2]);
     82         --tp2;
     83     }
     84 }st1,st2;
     85 int calc(int a,int b,int c)
     86 {
     87     if(a==-1||b==-1)    return -1;
     88     switch(c)
     89     {
     90     case 1:
     91         return (a+b)%md;
     92     case 2:
     93         return (a-b+md)%md;
     94     case 3:
     95         return ll(a)*b%md;
     96     case 4:
     97         if(b==0)    return -1;
     98         return ll(a)*inv[b]%md;
     99     default:
    100         assert(0);
    101         return 0;
    102     }
    103 }
    104 void pop1()
    105 {
    106     int t1,t2,t3,t;
    107     t3=st2.top();st2.pop();
    108     t2=st1.top();st1.pop();
    109     if(st1.empty())
    110     {
    111         assert(t3==1||t3==2);
    112         t1=0;
    113     }
    114     else
    115     {
    116         t1=st1.top();st1.pop();
    117     }
    118     t=++mem;
    119     nn[t].type=t3;
    120     nn[t].d=calc(nn[t1].d,nn[t2].d,t3);
    121     nn[t].ch[0]=t1;nn[t].ch[1]=t2;
    122     st1.push(t);
    123 }
    124 int len;
    125 int calc_r1(int a,int b,int c)//找出x使得a c x = b
    126 {
    127     if(a==-2||b==-2)    return -2;
    128     if(a==-1||b==-1)    return -1;
    129     switch(c)
    130     {
    131     case 1:
    132         return calc(b,a,2);
    133     case 2:
    134         return calc(a,b,2);
    135     case 3:
    136         if(a==0)    return b==0?-1:-2;
    137         return calc(b,a,4);
    138     case 4:
    139         if(a==0)    return b==0?-1:-2;
    140         if(b==0)    return a==0?-1:-2;
    141         return calc(a,b,4);
    142     default:
    143         assert(0);
    144         return 0;
    145     }
    146 }
    147 int calc_r2(int a,int b,int c)//找出x使得x c a = b
    148 {
    149     if(a==-2||b==-2)    return -2;
    150     if(a==-1||b==-1)    return -1;
    151     switch(c)
    152     {
    153     case 1:
    154         return calc(b,a,2);
    155     case 2:
    156         return calc(b,a,1);
    157     case 3:
    158         if(a==0)    return b==0?-1:-2;
    159         return calc(b,a,4);
    160     case 4:
    161         if(a==0)    return -2;
    162         return calc(a,b,3);
    163     default:
    164         assert(0);
    165         return 0;
    166     }
    167 }
    168 void solve(int rt,int x)//x为要使得子树成为的值,-1->-1,-2->无解
    169 {
    170     //printf("t%d %d
    ",rt,x);
    171     if(nn[rt].type==0)  an[nn[rt].num]=x;
    172     else if(!nn[rt].ch[0])  solve(nn[rt].ch[1],calc_r1(0,x,nn[rt].type));
    173     else if(!nn[rt].ch[1])  assert(0);//solve(ch[0],x);
    174     else
    175     {
    176         //if(x<0)
    177         //printf("%d ch1 %d
    ",rt,nn[nn[rt].ch[1]].d);
    178         solve(nn[rt].ch[0],calc_r2(nn[nn[rt].ch[1]].d,x,nn[rt].type));
    179         //printf("%d ch0 %d
    ",rt,nn[nn[rt].ch[0]].d);
    180         solve(nn[rt].ch[1],calc_r1(nn[nn[rt].ch[0]].d,x,nn[rt].type));
    181     }
    182 }
    183 int rt;
    184 int main()
    185 {
    186     bool fl=0;
    187     int i,edpos=0,nowd,nowdep,t1;
    188     ma['+']=1;ma['-']=2;ma['*']=3;ma['/']=4;ma['(']=5;ma[')']=6;
    189     scanf("%d%d",&n,&md);
    190     inv[1]=1;
    191     for(i=2;i<md;i++)    inv[i]=ll(md-md/i)*inv[md%i]%md;
    192     scanf("%s",ss+1);len=strlen(ss+1);
    193     for(i=1;i<=len;i++)
    194     {
    195         if(isdigit1(ss[i]))
    196         {
    197             edpos=i;
    198             left=left*10+ss[i]-'0';
    199         }
    200         else
    201             break;
    202     }
    203     nowd=nowdep=0;
    204     for(i=edpos+2;i<=len;i++)
    205     {
    206         if(isdigit1(ss[i]))
    207         {
    208             fl=1;
    209             nowd=nowd*10+ss[i]-'0';
    210         }
    211         else
    212         {
    213             if(fl)
    214             {
    215                 fl=0;
    216                 ++plen;
    217                 pre[plen].d=nowd;pre[plen].type=0;
    218                 nowd=0;
    219             }
    220             ++plen;
    221             pre[plen].type=ma[ss[i]];
    222         }
    223     }
    224     if(fl)
    225     {
    226         ++plen;
    227         pre[plen].d=nowd;pre[plen].type=0;
    228     }
    229     for(i=1;i<=plen;i++)
    230     {
    231         if(pre[i].type==0&&pre[i].num!=-1)
    232         {
    233             pre[i].num=++mem;
    234             nn[mem].type=0;nn[mem].d=pre[i].d;nn[mem].num=i;
    235         }
    236     }
    237     for(i=1;i<=plen;i++)
    238     {
    239         if(pre[i].type==5)
    240         {
    241             st1.add_stack();st2.add_stack();
    242         }
    243         else if(pre[i].type==6)
    244         {
    245             while(!st2.empty()) pop1();
    246             t1=st1.top();st1.pop();
    247             st1.del_stack();st2.del_stack();
    248             st1.push(t1);
    249         }
    250         else if(pre[i].type==0)
    251         {
    252             st1.push(pre[i].num);
    253         }
    254         else
    255         {
    256             while(!st2.empty()&&order[st2.top()]>=order[pre[i].type])
    257                 pop1();
    258             st2.push(pre[i].type);
    259         }
    260     }
    261     while(!st2.empty())pop1();//{printf("tt%d
    ",st2.top());st2.pop();}
    262     //while(!st1.empty()){printf("2t%d
    ",st1.top());st1.pop();}
    263     rt=st1.top();st1.pop();
    264     /*
    265     for(i=1;i<=mem;i++)
    266     {
    267         printf("%d %d ",i,nn[i].type);
    268         if(nn[i].type==0)   printf("%d ",nn[i].d);
    269         else printf("%d %d ",nn[i].ch[0],nn[i].ch[1]);
    270         printf("%d ",nn[i].d);
    271         puts("");
    272     }
    273     */
    274     solve(rt,left);
    275     for(i=1;i<=plen;i++)
    276         if(pre[i].type==0)
    277         {
    278             if(an[i]==-2)   puts("No Solution");
    279             else    printf("%d
    ",an[i]);
    280         }
    281     return 0;
    282 }
    View Code

    事实上并不要的...只要把左括号放进栈,然后每一次做运算时保证不弹栈顶左括号(由于前置的-/+,可能弹不出来数,弹不出来了就弹0)

    搞不清楚,还是前面那样写了..反正只是多点代码量,写写很快的

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<vector>
      5 #include<cmath>
      6 using namespace std;
      7 #define fi first
      8 #define se second
      9 #define mp make_pair
     10 #define pb push_back
     11 typedef long long ll;
     12 typedef unsigned long long ull;
     13 typedef pair<int,int> pii;
     14 template<class T>
     15 struct mstack
     16 {
     17     T d1[1001000];
     18     size_t d2[1001000],tp1,tp2;
     19     mstack():tp1(0),tp2(1){d2[1]=0;}
     20     bool empty(){return tp1==d2[tp2];}
     21     T top(){return empty()?0:d1[tp1];}
     22     void pop(){if(!empty())--tp1;}
     23     void push(const T &x){d1[++tp1]=x;}
     24     void del_stack(){--tp2;}
     25     void add_stack(){d2[++tp2]=tp1;}
     26 };
     27 mstack<double> st1;
     28 mstack<char> st2;
     29 int od[2333];
     30 double calc(double a,double b,char c)
     31 {
     32     //printf("tt%f %f %c
    ",a,b,c);
     33     switch(c)
     34     {
     35     case '+':
     36         return a+b;
     37     case '-':
     38         return a-b;
     39     case '*':
     40         return a*b;
     41     case '/':
     42         return a/b;
     43     case '^':
     44         return pow(a,b);
     45     default:
     46         return 233;
     47     }
     48 }
     49 char s[1001000];
     50 int len;
     51 bool ok(char a,char b)//x a y b z是否先运算a
     52 {
     53     if(a=='^'&&b=='^')  return 0;
     54     return od[a]>=od[b];
     55 }
     56 int main()
     57 {
     58     int i,tlen;double a,b,tt;char c;
     59     od['+']=od['-']=1;od['*']=od['/']=2;od['^']=3;
     60     scanf("%s",s);len=strlen(s);
     61     for(i=0;i<len;)
     62     {
     63         //printf("ttt%d
    ",i);
     64         switch(s[i])
     65         {
     66         case '(':
     67             st1.add_stack();st2.add_stack();
     68             i++;
     69             break;
     70         case '+':
     71         case '-':
     72         case '*':
     73         case '/':
     74         case '^':
     75             while(!st2.empty()&&ok(st2.top(),s[i]))
     76             {
     77                 c=st2.top();st2.pop();
     78                 b=st1.top();st1.pop();
     79                 a=st1.top();st1.pop();
     80                 st1.push(calc(a,b,c));
     81             }
     82             st2.push(s[i]);
     83             i++;
     84             break;
     85         case ')':
     86             while(!st2.empty())
     87             {
     88                 c=st2.top();st2.pop();
     89                 b=st1.top();st1.pop();
     90                 a=st1.top();st1.pop();
     91                 st1.push(calc(a,b,c));
     92             }
     93             a=st1.top();st1.pop();
     94             st1.del_stack();st2.del_stack();
     95             st1.push(a);
     96             i++;
     97             break;
     98         default:
     99             sscanf(s+i,"%lf%n",&tt,&tlen);
    100             st1.push(tt);
    101             i+=tlen;
    102         }
    103     }
    104     while(!st2.empty())
    105     {
    106         c=st2.top();st2.pop();
    107         b=st1.top();st1.pop();
    108         a=st1.top();st1.pop();
    109         st1.push(calc(a,b,c));
    110     }
    111     printf("%.2f",st1.top());
    112     return 0;
    113 }
    View Code

    可以用sscanf直接读数字,用%n获取读取过程中消耗的字符数

  • 相关阅读:
    VB 进程权限提升 代码
    不錯的超超鏈接title效果以及一個輸入flash的js
    关于用Virtual PC 2004 SP1装Red Hat Linux花屏的问题
    apache2+mysql5+php5在linux下的安装过程
    DEBUG命令详解
    VBKiller使用说明
    Intel奔騰系列CPU指令全集(包含P4)
    微代码和汇编语言的区别
    用DELPHI为ASP开发文件上载组件
    一個不錯的超鏈接的title效果
  • 原文地址:https://www.cnblogs.com/hehe54321/p/8044550.html
Copyright © 2020-2023  润新知