• 利用栈进行表达式求解


        以前A掉的表达式求解统统是递归= =,栈一直不知道怎么搞,今天稍微看了看,写了一个较简单的。

        对于一个合法的表达式,只要知道运算符的优先级即可利用栈求解,貌似是将中缀表达式转化为了后缀表达式,这些个名词咳咳= =

        顾名思义后缀表达式就是运算符写在后面嘛,对于a+b就是ab+ ,我们就知道要计算ab的和,对于一些更复杂状态的式子,显然需要一些技巧。

        先来看一道简单的题目    http://acm.nyist.net/JudgeOnline/problem.php?pid=1272  

        注意到这个题目中只有Smax一个函数所以可以用逗号来替代这个函数更加简便,我们用两个栈保存中间变量,一个储存符号的栈sc,一个储存中间值的栈si,还要有一个优先级表。

        当前字符如果是一个数字那就计算出连续的这个数字并加入到si中,如果是个字符的话,与sc栈顶字符比较优先级,如果等于栈顶那就出栈(对于'(',')'这些特殊的匹配符号),如果大于栈顶那么说明应该先执行这个运算符,

    入栈即可,如果小于栈顶,说明我们要用掉栈顶的运算符,取出si中的两个数后根据栈顶符号计算后再将结果加入到si中,注意到可能有多个需要计算的运算符所以这里用一个循环表达。为了方便引入'#'这个匹配字符,这样不用判断栈空的情况,显然最后sc中只有一个数字,就是答案了。

      

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<map>
     7 #include<stack>
     8 #include<ctype.h>
     9 using namespace std;
    10 #define inf 0x3f3f3f3f
    11 char opt[]={'=',',','*','(',')','#'};
    12 int g[10][10]={
    13 {1,1,-1,-1,1,1},
    14 {-1,1,-1,-1,1,1},
    15 {1,1,1,-1,1,1},
    16 {-1,-1,-1,-1,0,1},
    17 {1,1,1,0,1,1},
    18 {-1,-1,-1,-1,-1,0}
    19 };
    20 map<char,int>M;
    21 char s[330];
    22 stack<char>sc;
    23 stack<int>si;
    24 int num(int N)
    25 {
    26     int r=0; while(N){r+=N%10;N/=10;}
    27     return r;
    28 }
    29 int cal(int a,int b,char ch)
    30 {
    31     switch(ch){
    32     case '+':return a+b;break;
    33     case '*':return a*b;break;
    34     case ',':return max(num(a),num(b));break;
    35     }
    36 }
    37 int main()
    38 {
    39     int T,N,i,j,k;
    40     for(i=0;i<6;++i)
    41         M[opt[i]]=i;
    42     cin>>T;
    43     while(T--){
    44         scanf("%s",s);
    45         N=strlen(s);
    46         s[N]='#';
    47         while(!sc.empty())sc.pop();
    48         while(!si.empty())si.pop();
    49         sc.push('#');
    50         for(i=0;i<=N;++i)
    51         {
    52             int t=-1;
    53             if(isdigit(s[i])){
    54                 t=s[i]-'0';
    55                 while(isdigit(s[i+1])){
    56                     t=t*10+s[++i]-'0';
    57                 }
    58                 si.push(t);
    59             }
    60             else{bool ok=1;
    61             while(ok){
    62                 if(s[i]=='S')i+=4;
    63                 int x=g[M[sc.top()]][M[s[i]]];
    64                 if(x==0) ok=0,sc.pop();
    65                 else if(x==-1) ok=0,sc.push(s[i]);
    66                 else{
    67                     int a1=si.top();si.pop();
    68                     int a2=si.top();si.pop();
    69                     si.push(cal(a2,a1,sc.top()));
    70                     sc.pop();
    71                 }
    72             }
    73         }
    74         }
    75         cout<<si.top()<<endl;
    76     }
    77     return 0;
    78 }

    http://acm.hdu.edu.cn/showproblem.php?pid=1237

        有了四种运算+-*/ , 其实和上面的类似改下代码就能AC,当然可以写的更简单,不过为了练习栈就这样写了。

       

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<map>
     7 #include<stack>
     8 #include<ctype.h>
     9 using namespace std;
    10 #define inf 0x3f3f3f3f
    11 char opt[]={'+','-','*','/','(',')','#'};
    12 int g[10][10]={
    13 {1,1,-1,-1,-1,1,1},
    14 {1,1,-1,-1,-1,1,1},
    15 {1,1,1,1,-1,1,1},
    16 {1,1,1,1,-1,1,1},
    17 {-1,-1,-1,-1,-1,0,1},
    18 {1,1,1,1,0,1,1},
    19 {-1,-1,-1,-1,-1,-1,0}
    20 };
    21 map<char,int>M;
    22 char s[1005];
    23 stack<char>sc;
    24 stack<double>si;
    25 double cal(double a,double b,char ch)
    26 {
    27     switch(ch){
    28     case '+':return a+b;break;
    29     case '*':return a*b;break;
    30     case '-':return a-b;break;
    31     case '/':return a/b;break;
    32     }
    33 }
    34 int main()
    35 {
    36     int T,N,i,j,k;
    37     for(i=0;i<7;++i)
    38         M[opt[i]]=i;
    39     while(gets(s)){
    40         N=strlen(s);
    41         if(N==1&&s[0]=='0') break;
    42         s[N]='#';
    43         while(!sc.empty())sc.pop();
    44         while(!si.empty())si.pop();
    45         sc.push('#');
    46         for(i=0;i<=N;++i)
    47         {
    48             if(s[i]==' ') continue;
    49             double t=-1;
    50             if(isdigit(s[i])){
    51                 t=s[i]-'0';
    52                 while(isdigit(s[i+1])){
    53                     t=t*10+s[++i]-'0';
    54                 }
    55                 si.push(t);
    56             }
    57             else{bool ok=1;
    58             while(ok){
    59                 int x=g[M[sc.top()]][M[s[i]]];
    60                 if(x==0) ok=0,sc.pop();
    61                 else if(x==-1) ok=0,sc.push(s[i]);
    62                 else{
    63                     double a1=si.top();si.pop();
    64                     double a2=si.top();si.pop();
    65                     si.push(cal(a2,a1,sc.top()));
    66                     sc.pop();
    67                 }
    68             }
    69         }
    70         }
    71         printf("%.2f
    ",si.top());
    72     }
    73     return 0;
    74 }
  • 相关阅读:
    linux中添加ftp用户,并设置相应的权限
    mysql 命令管理
    阿里云服务器资料
    sql替换指定字段指定字符串
    apache本地域名ip重定向vhosts
    php数组序列化serialize与unserialize
    Android 开发第三天
    Android 开发第二天
    Android开发的第一天
    字符的截取方法使用的是Substring 和三目运算符
  • 原文地址:https://www.cnblogs.com/zzqc/p/7553220.html
Copyright © 2020-2023  润新知