中缀表达式求值总结

Posted 不明嚼栗的园子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了中缀表达式求值总结相关的知识,希望对你有一定的参考价值。

      中缀表达式的题目困扰了我两三年,都没去写过。。这两天看到2005年提高组的T3要用到所以心血来潮写了一下。

  表达式求值借助基本结构应该不用说了是栈,不管手写还是STL都没有太大关系。而中缀表达式最难控制的地方是优先级,算上+-*/^()一共有四个优先级【+-,*/,, ^()】(后面会提到一个三级的字符“负号”,这是预留空位)。

  下面对一个例子进行分析:2*3+4*6/3+17-4^2

  那么处理的时候怎么控制优先级呢?

  搜到‘+’之前,栈的情况是这样的:

      操作数栈:2  3

      操作符栈:*

  然后搜到+的时候因为*的优先级大,所以计算 2*3 ,并把结果6入栈,+入栈。

  然后搜到‘/’之前,栈的情况是这样的:

      操作数栈:6  4  6

      操作符栈:+  *

  因为*的优先级和/是一样的,所以先计算4*6,把结果24入栈,/入栈。

  以此类推,可以计算出整个式子的值

  

  然后来讨论负号问题。

  ‘-’可以当做减号,也可以当做负号。根据经验可知,如果‘-’前面是\')\'或者数字的时候用作减号,否则为负号。这里我要引用一位神犇的方法,把‘-’改为另一个负号比如说‘#’,优先级为3级(就是前面说的)。

  这样的话比如表达式-1+5就可以改为#1+5,计算的时候是先计算栈底的‘#’,因此答案为4。

  接下来要加入括号。我的解决方法是把括号看做一个独立的表达式,进行递归处理,每次完整计算一个括号内的表达式的值(毕竟这才符合计算规律)。

  于是就有了这样的代码(用了一下quicksum)(我删了几个函数)

  1 #include <iostream>
  2 #include <string>
  3 #include <stack>
  4 #include <map>
  5 using namespace std;
  6 
  7 string s;
  8 stack<int> a;
  9 stack<char> b;
 10 map<char,int> mp;
 11 int len;
 12 int it;
 13 
 14 int qsum(int a,int b)
 15 {
 16     int r=1;
 17     while (b)
 18     {
 19         if (b&1) r*=a;
 20         a*=a;
 21         b>>=1;
 22     }
 23     return r;
 24 }
 25 
 26 void ct()
 27 {
 28     int tmp=a.top();a.pop();
 29     char cc=b.top();b.pop();
 30     if (cc==\'#\')
 31     {
 32         a.push(0-tmp);
 33         return;
 34     }
 35     int tp=a.top();a.pop();
 36     switch (cc)
 37     {
 38         case \'+\':a.push(tmp+tp);break;
 39         case \'-\':a.push(tp-tmp);break;
 40         case \'*\':a.push(tmp*tp);break;
 41         case \'/\':a.push(tp/tmp);break;
 42         case \'^\':a.push(qsum(tp,tmp));break;
 43     }
 44 }
 45 
 46 void calc()
 47 {
 48     int xx=0;
 49     b.push(s[it]);
 50     it++;
 51     if (s[it]==\')\')
 52     {
 53         b.pop();return;
 54     }
 55     while (s[it]!=\')\')
 56     {
 57         if (isdigit(s[it]))
 58         {
 59             xx=xx*10+s[it]-\'0\';
 60         }
 61         else
 62         {
 63             if (isdigit(s[it-1]))
 64             {
 65                 a.push(xx);
 66                 xx=0;
 67             }
 68             switch (s[it])
 69             {
 70                 case \'(\':calc();break;
 71                 case \'+\':
 72                     if (mp[b.top()]>=1&&b.top()!=\'(\'&&b.top()!=\')\')
 73                         ct();
 74                     b.push(s[it]);
 75                     break;
 76                 case \'-\':
 77                     if (mp[b.top()]>=1&&b.top()!=\'(\'&&b.top()!=\')\')
 78                         ct();
 79                     b.push(s[it]);
 80                     break;
 81                 case \'*\':
 82                     if (mp[b.top()]>=2&&b.top()!=\'(\'&&b.top()!=\')\')
 83                         ct();
 84                     b.push(s[it]);
 85                     break;
 86                 case \'/\':
 87                     if (mp[b.top()]>=2&&b.top()!=\'(\'&&b.top()!=\')\')
 88                         ct();
 89                     b.push(\'/\');
 90                     break;
 91                 case \'^\':
 92                     if (mp[b.top()]>=4&&b.top()!=\'(\'&&b.top()!=\')\')
 93                         ct();
 94                     b.push(s[it]);
 95                     break;
 96                 case \'#\':
 97                     b.push(s[it]);
 98             }
 99         }
100         it++;
101     }
102     if (s[it-1]!=\')\')
103         a.push(xx);
104     while (b.top()!=\'(\')
105         ct();
106     b.pop();
107 }
108 
109 int main()
110 {
111     cin >> s;
112     mp[\'+\']=1;mp[\'-\']=1;mp[\'#\']=3;mp[\'*\']=2;
113     mp[\'^\']=4;mp[\'(\']=4;mp[\')\']=4;mp[\'/\']=2;
114     pipei();
115     len=s.size();
116     for (int i=0;i<len;i++)
117     {
118         if (i==0 && s[i]==\'-\')
119             s[i]=\'#\';
120         else
121         {
122             if (s[i]==\'-\' && !isdigit(s[i-1]) && s[i-1]!=\')\')
123                 s[i]=\'#\';
124         }
125     }
126     int tmp=0,x=0;
127     for (it=0;it<len;it++)
128     {
129         if (isdigit(s[it]))
130         {
131             x=x*10+s[it]-\'0\';
132         }
133         else
134         {
135             if (isdigit(s[it-1]))
136             {
137                 a.push(x);
138                 x=0;
139             }
140             if (s[it]==\'(\')
141             {
142                 calc();
143                 continue;
144             }
145             if (!b.empty())
146             {
147                 switch (s[it])
148                 {
149                     case \'+\':
150                         if (mp[b.top()]>=1)
151                             ct();
152                         b.push(s[it]);
153                         break;
154                     case \'-\':
155                         if (mp[b.top()]>=1)
156                             ct();
157                         b.push(s[it]);
158                         break;
159                     case \'*\':
160                         if (mp[b.top()]>=2)
161                             ct();
162                         b.push(s[it]);
163                         break;
164                     case \'/\':
165                         if (mp[b.top()]>=2)
166                             ct();
167                         b.push(\'/\');
168                         break;
169                     case \'^\':
170                         if (mp[b.top()]>=4)
171                             ct();
172                         b.push(s[it]);
173                         break;
174                     case \'#\':
175                         b.push(s[it]);
176                 }
177             }
178             else
179                 b.push(s[it]);
180         }
181     }
182     if (s[it-1]!=\')\')
183         a.push(x);
184     while (!b.empty())
185         ct();
186     cout << a.top() << "\\n";
187 }
View Code

  然后codevs上有一题有多余括号问题。既然出了这样的题目就表示多余的括号可以随便匹配咯所以我弄了很无聊的匹配(我居然往里面加括号woc)于是这是我单独处理括号的代码(只是多加了[]和{})。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <string>
 4 #include <stack>
 5 using namespace std;
 6 
 7 string s;
 8 stack<pair<char,int> > c;
 9 bool v[100001];
10 
11 void ist(int pos)
12 {
13     switch (s[pos])
14     {
15         case\')\':s.insert(pos,"(");break;
16         case\']\':s.insert(pos,"[");break;
17         case\'}\':s.insert(pos,"{");
18     }
19 }
20 
21 int main()
22 {
23     cin >> s;
24     for (int i=0;i<s.size();i++)
25     {
26         pair<char,int> ss;
27         ss.first=s[i];ss.second=i;
28         switch (s[i])
29         {
30             case \'(\':c.push(ss);v[i]=1;break;
31             case \'[\':c.push(ss);v[i]=1;break;
32             case \'{\':c.push(ss);v[i]=1;break;
33             case \')\':if (i==0) ist(i);
34                 if (!c.empty() && c.top().first==\'(\')
35                 {
36                     v[c.top().second]=0;
37                     c.pop();
38                 }
39                 else
40                 {
41                     ist(i);
42                     i++;
43                 }
44                 break;
45             case \']\':if (i==0) ist(i);
46                 if (!c.empty() && c.top().first==\'[\')
47                 {
48                     v[c.top().second]=0;
49                     c.pop();
50                 }
51                 else
52                 {
53                     ist(i);
54                     i++;
55                 }
56                 break;
57             case \'}\':if (i==0) ist(i);
58                 if (!c.empty() && c.top().first==\'{\')
59                 {
60                     v[c.top().second]=0;
61                     c.pop();    
62                 }
63                 else
64                 {
65                     ist(i);
66                     i++;
67                 }
68         }
69     }
70     for(int i=s.size();i>=0;i--)
71         if (v[i])
72         {
73             switch(s[i])
74             {
75                 case \'(\':s.insert(i+1,")");break;
76                 case \'[\':s.insert(i+1,"]");break;
77                 case \'{\':s.insert(i+1,"}");
78             }
79         }
80     cout << s;
81 }
View Code

  结合了一下变成超长的代码了。。。可以AC掉codevs上的2178哦

  1 #include <iostream>
  2 #include <string>
  3 #include <stack>
  4 #include <map>
  5 using namespace std;
  6 
  7 string s;
  8 stack<int> a;
  9 stack<char> b;
 10 map<char,int> mp;
 11 int len;
 12 int it;
 13 stack<pair<char,int> > c;
 14 bool v[100001];
 15 
 16 int qsum(int a,int b)
 17 {
 18     int r=1;
 19     while (b)
 20     {
 21         if (b&1) r*=a;
 22         a*=a;
 23         b>>=1;
 24     }
 25     return r;
 26 }
 27 
 28 void ct()
 29 {
 30     int tmp=a.top();a.pop();
 31     char cc=b.top();b.pop();
 32     if (cc==\'#\')
 33     {
 34         a.push(0-tmp);
 35         return;
 36     }
 37     int tp=a.top();a.pop();
 38     switch (cc)
 39     {
 40         case \'+\':a.push(tmp+tp);break;
 41         case \'-\':a.push(tp-tmp);break;
 42         case \'*\':a.push(tmp*tp);break;
 43         case \'/\':a.push(tp/tmp);break;
 44         case \'^\':a.push(qsum(tp,tmp));break;
 45     }
 46 }
 47 
 48 void calc()
 49 {
 50     int xx=0;
 51     b.push(s[it]);
 52     it++;
 53     if (s[it]==\')\')
 54     {
 55         b.pop();return;
 56     }
 57     while (s[it]!=\')\')
 58     {
 59         if (isdigit(s[it]))
 60         {
中缀表达式求值的思路分析与代码实现

中缀表达式求值的方法—栈

中缀表达式转换成后缀表达式并求值

全网最高端?中缀表达式转为后缀表达式以及求值(可用于负数,阶乘)

中缀表达式求值

中缀表达式转为后缀表达式(逆波兰式)求值