表达式求值,中缀后缀转换,表达式递归直接求值等相关算法的实现

当前算法都未考虑多个优先级的问题,仅仅考虑+,-,*,/与()
//expression.h
  1 /*
  2  * =====================================================================================
  3  *    Filename:  expression.h
  4  *    Description:  
  5  *      各种与表达式相关的算法
  6  *      如中缀转后缀
  7  *      后缀表达式求值
  8  *      中缀表达式递归求值
  9  * =====================================================================================
 10  */
 11 #ifndef _EXPRESSION_H_
 12 #define _EXPRESSION_H_
 13 #include <string>
 14 #include <stack>
 15 #include <iostream>
 16 #include <algorithm>
 17 #include <sstream>
 18 #include <vector>
 19 #include <list>
 20 #include <assert.h>
 21 
 22 using namespace std;
 23 
 24 namespace binary_tree {
 25 //二叉树前置声明
 26 template<typename T>
 27 class BinaryTreeNode;
 28 
 29 template<typename U, typename T>
 30 class BinaryTree;
 31 
 32 template<typename T>
 33 class SimpleBinaryTreeNode;
 34 
 35 template<typename U, typename T>
 36 class SimpleBinaryTree;
 37 }
 38 
 39 namespace expression {
 40 
 41 //typedef binary_tree::BinaryTreeNode<string> Node;
 42 //typedef binary_tree::BinaryTree<string,Node> Tree; 
 43 typedef binary_tree::SimpleBinaryTreeNode<string> Node;
 44 typedef binary_tree::SimpleBinaryTree<string,Node> Tree;
 45 
 46 /*对外接口********************************************************/
 47 //中缀表达式带括号转后缀,支持浮点
 48 //用户输入有错误会识别出来报错,不做修正
 49 bool Infix2Suffix(string infix_string, string &suffix_string);
 50 
 51 //后缀表达式求值,注意后缀表达式是用" "隔开的
 52 double EvaluateSuffixString(const string  &suffix_string);
 53 
 54 //判断给出的中缀表达式是否正确,括号匹配正确,无特殊字符,否则报错
 55 bool InfixStringNormallize(string &infix_string);
 56 
 57 //中缀表达式直接求值,要求中缀表达式格式正确,且按空格隔开
 58 //递归求解
 59 double EvaluateInfixString(const string& infix_string);
 60 /****************************************************************/
 61 
 62 
 63 template <class T> 
 64 T ConvertString2Num(const std::string &s) {
 65     T value;
 66     std::stringstream ss(s);
 67     ss >> value;
 68     return value;
 69 }
 70 //template <class T> 
 71 //void ConvertString2Num(const std::string &s, T &value) {
 72 //    std::stringstream ss(s);
 73 //    ss >> value;
 74 //}
 75 
 76 //当前只考虑+ - * / 4种运算符号
 77 //+ -  优先级为 0
 78 //* /  优先级为 1
 79 int Priority(const char op); 
 80 
 81 //分析是否为数字,判断一个字符
 82 inline bool IsDigit(const char input);
 83 //分析整个string是否为数字,头一位是数字就是数字或者头一位-,-3
 84 inline bool IsNum(const string& s);
 85 
 86 double EvaluateInfixStringHelp(const vector<string> &vec);
 87 //找到根节点后将原数组分成左右两部分供递归调用
 88 void SplitVec(const vector<string> &vec, vector<string> &vec_left, 
 89               vector<string> &vec_right, char &op); 
 90 
 91 //用vector下标的这个版本有bug TODO  (3+2)*4+2
 92 double EvaluateInfixStringHelp(const vector<string> &vec, int begin, int end); 
 93 void SplitVec(const vector<string> &vec, 
 94               const int begin, const int end, 
 95               int &left_begin, int &left_end,
 96               int &right_begin, int &right_end,
 97               char &op);
 98 
 99 //using list
100 double EvaluateInfixString2(const string& infix_string);
101 double EvaluateInfixStringHelp2(list<string> &l);
102 void SplitList(list<string> &l, list<string> &list_left, 
103                list<string> &list_right, char &op);
104 
105 
106 //由标准中缀表达式建立表达式二叉树
107 void CreateExpressionBinaryTree(const string& infix_string,
108                                 Tree &binary_tree);
109 Node*  CreateExpressionBinaryTreeHelp(
110                             const vector<string> &vec);
111 
112 }       //end of namespace expression
113 #endif  //end of _EXPRESSION_H_
//expression.cc
  1 #include "expression.h"
  2 #include "binary_tree.h"
  3 using std::stack;
  4 using std::string;
  5 using std::cout;
  6 using std::endl;
  7 namespace expression {
  8 
  9 //op + - * / (
 10 //num data and )
 11 //用于检测输入是否正确,不是传统的数字,操作符定义
 12 enum State{op,num};
 13 
 14 //string 转成double等任意类型
 15 //当前只考虑+ - * / 4种运算符号
 16 //+ -  优先级为 0
 17 //* /  优先级为 1
 18 int Priority(const char op) {
 19     int priority;
 20     switch(op) {
 21         case '+'case '-':
 22             priority = 0;
 23             break;
 24         case '*'case '/':
 25             priority = 1;
 26             break;
 27         case '(':
 28             priority = -1// we need it to stop pop like (3 + 4 + 5),监视哨,到了(停下
 29             break;
 30         default:
 31             cout << "error" << endl;
 32             break;
 33     }
 34     return priority;
 35 }
 36 
 37 //分析是否为数字
 38 inline bool IsDigit(const char input) {
 39     return input >= '0' && input <= '9';
 40 }
 41 
 42 //中缀表达式带括号转后缀,支持浮点
 43 //用户输入有错误会识别出来报错,不做修正
 44 //允许用户输入冗余的初始括号,(a+b),视为正确输入
 45 //同时处理是时对于没有最外层括号的也加上便于处理
 46 //判断过程,对于运算符前面的比栈里的priority小或者相等的运算符要出栈,被计算
 47 //然后当前的入栈
 48 //对于(入栈
 49 //对于),将栈里的运算符都pop,被计算,将( pop
 50 //对于数字,直接输出
 51 //表达式正确性判断,判断了括号是否匹配,利用栈
 52 //直接判断有无错误输入字符
 53 //通过状态位,op,num判断是否连续输入数字,或者操作符错误
 54 //或者(前输入了),数字错误
 55 //或者)前输入了操作符,(错误
 56 //括号)视为num,要求前面也为num
 57 //括号(视为op,要求前面也为op
 58 //数字视为num,要求前面为op
 59 //运算符视为op,要求前面为num
 60 bool Infix2Suffix(string infix_string, string &suffix_string){
 61     stack<char> s;    //notice we use char not string because elements of string is char
 62     suffix_string.clear(); 
 63     //预处理强制最外层加括号 方便统一处理,这样不需要最后的多余一步栈内处理
 64     infix_string = '(' + infix_string;
 65     infix_string += ')';
 66     
 67     //转换核心部分
 68     int len = infix_string.length();
 69     State state = op;   //开始第一个为(,状态为op
 70     for (int i = 0; i < len; i++) {
 71         //处理数字情况 遇到一个数字就把它整个数找到,然后处理下一个字符op
 72         //要考虑到 3.34浮点数的处理,要考虑到-3.34负数的处理数字处理
 73         //的共同特点是最后结束位一定是数字
 74         int dot_flag = 0;   //允许处理浮点数allow only one . like 3.332
 75         int i2 = i;
 76         while (i < len && 
 77               (IsDigit(infix_string[i]) ||
 78               (i < len -1 && infix_string[i]== '-'  //-3被视为数字处理
 79               && IsDigit(infix_string[i + 1])))) {
 80             suffix_string += infix_string[i];
 81             i++;
 82             if (i < len && !dot_flag && infix_string[i] == '.') { //浮点数字处理
 83                 suffix_string += infix_string[i];
 84                 i++;
 85                 dot_flag = 1;
 86             }
 87         }
 88 
 89         if (i > i2 && IsDigit(infix_string[i-1])) {     // i>i2则表明刚处理了数字
 90             suffix_string += ' ';
 91             if (state != op) {          //数字前面应该是运算符或者(
 92                 suffix_string.clear();
 93                 return false;
 94             }
 95             state = num;
 96         } else if (i > i2 && dot_flag == 1) {
 97             return false;   //case like 3. 
 98         }
 99 
100 
101         if (i == len)   //we have done,(处理完最后一个数)
102             break;
103         
104         //处理操作符,非数字情况
105         switch(infix_string[i]) {
106             case '(':
107                 if (state != op)    // (前面应该是运算符符或者(,左括号按照op处理
108                     return false;
109                 //state = op;
110                 s.push('(');
111                 break;
112             case ')':
113                 if (state != num)   // )前面应该是数字或者),右括号按照num处理
114                     return false;
115                 //state = num;
116                 while(!s.empty() && s.top() != '(') {   //如果能确保输入括号的正确性,则不需要!s.empty()的判断
117                     suffix_string += s.top();
118                     suffix_string += ' ';
119                     s.pop();
120                 }
121                 if (s.empty()) //括号不匹配,缺左括号
122                     return false;
123                 s.pop();  // pop  '('
124                 break;
125             case '+'case '-'case '*'case '/'
126                 if (state != num)       //运算符前面应该是数字或者)
127                     return false;
128                 state = op;
129                 while(!s.empty() && s.top() != '(' &&
130                       (Priority(infix_string[i]) <= Priority(s.top()))) {   //如果能确保输入括号的正确性,则不需要!s.empty()的判断
131                     suffix_string += s.top();
132                     suffix_string += ' ';
133                     s.pop();
134                 }
135                 s.push(infix_string[i]);
136                 break;
137             case ' 'case '\t'case '\r':     //空格允许,但不处理, linux读的行是带\r的
138                 break;
139             default:    //遇到意外字符,输入有误
140                 cout << "Unexpeced input, error, check your input" << endl;
141                 return false;
142         }
143     }
144     if (state != num)   //容易忽略,表达式尾部需要是数字
145         return false;
146     if (!s.empty()) //括号不匹配,左括号多,注意如果没有预处理的加最外面的括号,则需要继续pop出栈的
147         return false;
148     //去掉最后的空格
149     suffix_string.erase(string::size_type(suffix_string.size()-1), string::size_type(1));
150     //OK,finally convert sucessfully
151     return true;
152 }
153 
154 
155 inline bool IsNum(const string& s) {
156     return IsDigit(s[0]) || (s[0== '-' && IsDigit(s[1]));
157 }
158 
159 //后缀表达式求值,注意后缀表达式是用" "隔开的
160 double EvaluateSuffixString(const string  &suffix_string) {
161     stringstream ss(suffix_string);
162     double elem, p, p1, p2;
163     string sub_str;
164     stack<double> s;
165     while(getline(ss,sub_str,' ')) {
166         //处理数字
167         if (IsNum(sub_str)) {
168             elem = ConvertString2Num<double>(sub_str);
169             s.push(elem);
170         } else {    //运算符
171             p2 = s.top();
172             s.pop();
173             p1 = s.top();
174             s.pop();
175             switch(sub_str[0]) {
176                 case '+':
177                     p = p1 + p2;
178                     break;
179                 case '-':
180                     p = p1 - p2;
181                     break;
182                 case '*':
183                     p = p1 * p2;
184                     break;
185                 case '/':
186                     p = p1 / p2;
187                     break;
188                 default:
189                     cout << "error operator" << endl;
190                     break;
191             }
192             s.push(p);
193         }      
194     }
195     return s.top();
196 }
197 
198 //判断给出的中缀表达式是否正确,括号匹配正确,无特殊字符,否则报错
199 //如果是正确的化转换成标准带空格的中缀表达式,如果有最外层括号,去掉
200 //(3+2) 视为正确的输入但是转换为3 + 2
201 //(3+2)*(4+6) 注意这样是没有最外层括号的
202 bool InfixStringNormallize(string &infix_string) {
203     //如果有最外层的括号,去掉它
204     int len = infix_string.length();
205     string infix_string2; //临时转换结果
206 
207     stack<int> s;
208     int sum = 0;  //标记是第几个(, 当如果末尾是)并且将0号(pop出来则有最外层括号
209     int pre_sum = -1//标记当前是哪个标号的(出栈
210     State state = op;   //开始第一个为数字或者左括号,期待前面是op
211     bool flag_bracket = false//是否有最外层的括号:
212 
213     for (int i = 0; i < len; i++) {
214        int dot_flag = 0;   //允许处理浮点数allow only one . like 3.332
215         int i2 = i;
216         while (i < len && 
217               (IsDigit(infix_string[i]) ||
218               (i < len -1 && infix_string[i]== '-'  //-3被视为数字处理
219               && IsDigit(infix_string[i + 1])))) {
220             infix_string2 += infix_string[i];
221             i++;
222             if (i < len && !dot_flag && infix_string[i] == '.') { //浮点数字处理
223                 infix_string2 += infix_string[i];
224                 i++;
225                 dot_flag = 1;
226             }
227         }
228 
229         if (i > i2 && IsDigit(infix_string[i-1])) {     // i>i2则表明刚处理了数字
230             infix_string2 += ' ';
231             if (state != op) {          //数字前面应该是运算符或者(
232                 infix_string2.clear();
233                 return false;
234             }
235             state = num;
236         } else if (i > i2 && dot_flag == 1) {
237             return false;   //case like 3. 
238         }
239 
240         
241         if (i == len)   //we have done,(处理完最后一个数)
242             break;
243        
244         //处理操作符,非数字情况
245         switch(infix_string[i]) {
246             case '(':
247                 if (state != op)    // (前面应该是运算符符或者(,左括号按照op处理
248                     return false;
249                 //state = op;
250                 s.push(sum++);
251                 infix_string2 += '(';
252                 infix_string2 += ' ';
253                 break;
254             case ')':
255                 if (state != num)   // )前面应该是数字或者),右括号按照num处理
256                     return false;
257                 //state = num;
258                 if(s.empty())       //无左括号匹配
259                     return false;
260                 infix_string2 += ')';
261                 infix_string2 += ' ';
262                 pre_sum = s.top();
263                 s.pop();
264                 break;
265             case '+'case '-'case '*'case '/'
266                 if (state != num)       //运算符前面应该是数字或者)
267                     return false;
268                 state = op;
269                 infix_string2 += infix_string[i];
270                 infix_string2 += ' ';
271                 break;
272             case ' 'case '\t'case '\r':     //空格允许,但不处理, linux读的行是带\r的
273                 break;
274             default:    //遇到意外字符,输入有误
275                 cout << "Unexpeced input, error, check your input" << endl;
276                 return false;
277         }
278     }
279     if (state != num)   //容易忽略,表达式尾部需要是数字
280         return false;
281     if (!s.empty())     //(未被匹配完
282         return false;
283     //注意infix_string2最后有一个多余的空格
284     int start = 0;
285     int end = infix_string2.size() - 2;
286     //最左边是(,最右边是),并且(是最后一个出栈的(,就是最外层有(),需要去除的情况
287     if (infix_string2[start] == '(' && infix_string2[end] == ')' && pre_sum == 0 )
288         flag_bracket = true;
289     if (flag_bracket) //去括号,注意空格
290         infix_string.assign(infix_string2.begin() + 2, infix_string2.end() - 3);
291     else    //不需要去括号,但注意末尾的多余空格
292         infix_string.assign(infix_string2.begin(), infix_string2.end()- 1);
293     return true;
294 }
295 
296 //中缀表达式直接求值,要求中缀表达式格式正确,且按空格隔开
297 //递归求解
298 //首先找根节点,根节点是括号外面的最后一个 +/-,或者*/ 如果括号外面没有+ -
299 //开始的时候处理成没有最外面括号的,但后面要再保证不出现
300 //忽略了括号问题,晕了,当出现例如(3+2)的时候,需要破括号
301 //唉,什么时候能够一遍写对呢? :) 思维不够缜密全面
302 //注意这种情况 (3+2)*(4+5) + 3 不能去成3+2)*(4+5
303 //所以从右向左扫描字符串
304 // TODO 当前函数只考虑了存在 + - 和 * /两种优先级的情况
305 
306 //找根节点,本质上是找优先级最低的前提下最靠近右边的,如果有多个优先级,代码需要重写
307 //分裂可以修改函数改为只用下标标示分裂后的vec不需要真的assign,但可读性差
308 //或者改为list分裂 TODO 当前递归深度为d,就会用到d*(vec.size())的空间,每次向下都要新开vec.szie()的vec
309 //当前,可读最好,性能最差
310 //用下标递归,可读最差,性能最好
311 //用list 都居中
312 
313 
314 //注意这里用的end 指向最后一个元素
315 //而不是像vector end()指向末尾后面的元素
316 void SplitVec(const vector<string> &vec, 
317               const int begin, const int end, 
318               int &left_begin, int &left_end,
319               int &right_begin, int &right_end,
320               char &op) {
321     int pos = -1;
322     int candidate_pos = -1;
323     bool visited = false;  //是否已经遇到过* /
324     stack<int> s; //s空表示在括号外部,每次入栈值+1
325     int sum = 0;  //sum = 0表示入的是第一个括号,如果该括号最后才被出栈,则证明有最外()需要去除
326     int pre_sum = -1//别忘了,因为*/ 是暂时人选,后面继续变化,但是如果最终选择,需要恢复其所有信息,包括最外括号信息
327     int pre_sum_candidate = -1;
328     char candidate_op;
329     bool left_flag = false;   //是否有最外括号要去掉
330     bool right_flag = false;
331     //从右向左扫描数组
332     for (int i = end; i >= begin; i--) {
333         if (IsNum(vec[i]))
334             continue;
335         switch(vec[i][0]) {
336             case ')':
337                 s.push(sum++);
338                 break;
339             case '(':
340                 pre_sum = s.top();
341                 s.pop();
342                 break;
343             case '+'case '-':
344                 if (s.empty()) {
345                     pos = i;
346                     op = vec[i][0];
347                 }
348                 break;
349             case '*'case '/':
350                 if (s.empty() && !visited) {
351                     candidate_pos = i;
352                     candidate_op = vec[i][0];
353                     visited = true;
354                     pre_sum_candidate = pre_sum;
355                 }
356                 break;
357             default:
358                 cout << "error operator" << endl;
359                 break;
360         }
361         if (pos != -1)  //已经遇到括号外面的+ -了结束 
362             break;
363     }
364 
365     if (pos == -1) {
366         pos = candidate_pos;
367         op = candidate_op;
368         pre_sum = pre_sum_candidate;
369     }
370     if (vec[pos+1][0== '(' && vec[end][0== ')' && pre_sum == 0)
371         right_flag = true;
372     sum = 0;
373     pre_sum = -1;
374     //破括号!否则所有的符号都在括号内,无法继续了
375     if (vec[begin][0== '(' && vec[pos-1][0== ')') {
376         for (int i = begin; i < pos; i++) {
377             if (vec[i][0== '(')
378                 s.push(sum++);
379             if (vec[i][0== ')') {
380                 pre_sum = s.top();
381                 s.pop();
382             }
383         }
384         if (pre_sum == 0)
385             left_flag = true;
386     }
387 
388     // write the result
389     if (left_flag) {
390         left_begin = begin + 1;
391         left_end =  pos - 2;
392     } else {
393         left_begin = begin;
394         left_end =  pos - 1;
395     }
396     
397     if (right_flag) {
398         right_begin = pos + 2;
399         right_end = end - 1;
400     } else {
401         right_begin = pos + 1;
402         right_end = end;
403     }
404 
405 }
406 void SplitVec(const vector<string> &vec, vector<string> &vec_left, 
407               vector<string> &vec_right, char &op) {
408     assert(vec.size() >= 3); //at least 3 + 2 using 3 space
409     int pos = -1;
410     int candidate_pos = -1;
411     bool visited = false;  //是否已经遇到过* /
412     stack<int> s; //s空表示在括号外部,每次入栈值+1
413     int sum = 0;  //sum = 0表示入的是第一个括号,如果该括号最后才被出栈,则证明有最外()需要去除
414     int pre_sum = -1//别忘了,因为*/ 是暂时人选,后面继续变化,但是如果最终选择,需要恢复其所有信息,包括最外括号信息
415     int pre_sum_candidate = -1;
416     char candidate_op;
417     bool left_flag = false;   //是否有最外括号要去掉
418     bool right_flag = false;
419     //从右向左扫描数组
420     for (int i = vec.size() - 1; i >= 0; i--) {
421         if (IsNum(vec[i]))
422             continue;
423         switch(vec[i][0]) {
424             case ')':
425                 s.push(sum++);
426                 break;
427             case '(':
428                 pre_sum = s.top();
429                 s.pop();
430                 break;
431             case '+'case '-':
432                 if (s.empty()) {
433                     pos = i;
434                     op = vec[i][0];
435                 }
436                 break;
437             case '*'case '/':
438                 if (s.empty() && !visited) {
439                     candidate_pos = i;
440                     candidate_op = vec[i][0];
441                     visited = true;
442                     pre_sum_candidate = pre_sum;
443                 }
444                 break;
445             default:
446                 cout << "error operator" << endl;
447                 break;
448         }
449         if (pos != -1)  //已经遇到括号外面的+ -了结束 
450             break;
451     }
452 
453     if (pos == -1) {
454         pos = candidate_pos;
455         op = candidate_op;
456         pre_sum = pre_sum_candidate;
457     }
458     if (vec[pos+1][0== '(' && vec[vec.size()-1][0== ')' && pre_sum == 0)
459         right_flag = true;
460     sum = 0;
461     pre_sum = -1;
462     //破括号!否则所有的符号都在括号内,无法继续了
463     if (vec[0][0== '(' && vec[pos-1][0== ')') {
464         for (int i = 0; i < pos; i++) {
465             if (vec[i][0== '(')
466                 s.push(sum++);
467             if (vec[i][0== ')') {
468                 pre_sum = s.top();
469                 s.pop();
470             }
471         }
472         if (pre_sum == 0)
473             left_flag = true;
474     }
475     if (left_flag)
476         vec_left.assign(vec.begin() + 1, vec.begin() + pos - 1);
477     else
478         vec_left.assign(vec.begin(), vec.begin() + pos);
479     if (right_flag)
480         vec_right.assign(vec.begin() + pos + 2, vec.end() - 1);
481     else
482         vec_right.assign(vec.begin() + pos + 1, vec.end());
483 }
484 
485 double EvaluateInfixStringHelp(const vector<string> &vec, int begin, int end) {
486     if (begin == end) {
487         return ConvertString2Num<double>(vec[begin]);
488     }
489 
490     int left_begin, left_end, right_begin, right_end;
491     char op;
492 
493     SplitVec(vec, begin, end, 
494              left_begin, left_end, 
495              right_begin, right_end, op);
496 
497     switch(op) {
498         case '+':
499             return EvaluateInfixStringHelp(vec, left_begin, left_end) +
500                    EvaluateInfixStringHelp(vec, right_begin, right_end);
501             break;
502         case '-':
503             return EvaluateInfixStringHelp(vec, left_begin, left_end) - 
504                    EvaluateInfixStringHelp(vec, right_begin, right_end);
505             break;
506         case '*':
507             return EvaluateInfixStringHelp(vec, left_begin, left_end) *
508                    EvaluateInfixStringHelp(vec, right_begin, right_end);
509             break;
510         case '/':
511             return EvaluateInfixStringHelp(vec, left_begin, left_end) /
512                    EvaluateInfixStringHelp(vec, right_begin, right_end);
513             break;
514         default:
515             break;
516     }
517 
518 }
519 double EvaluateInfixStringHelp(const vector<string> &vec) {
520     //递归出口,只有一个数字
521     if (vec.size() == 1)    
522         return ConvertString2Num<double>(vec[0]);
523     
524     vector<string> vec_left, vec_right; 
525     char op; //根的内容
526     
527     SplitVec(vec, vec_left, vec_right, op);
528 
529     switch(op) {
530         case '+':
531             return EvaluateInfixStringHelp(vec_left) +
532                    EvaluateInfixStringHelp(vec_right);
533             break;
534         case '-':
535             return EvaluateInfixStringHelp(vec_left) - 
536                    EvaluateInfixStringHelp(vec_right);
537             break;
538         case '*':
539             return EvaluateInfixStringHelp(vec_left) *
540                    EvaluateInfixStringHelp(vec_right);
541             break;
542         case '/':
543             return EvaluateInfixStringHelp(vec_left) /
544                    EvaluateInfixStringHelp(vec_right);
545             break;
546         default:
547             break;
548     }
549 }
550 
551 //要求执行之前infix_string 已经被normalize,
552 //空格间隔,没有最外层括号
553 double EvaluateInfixString(const string& infix_string) {
554     stringstream ss(infix_string);
555     string sub_str;
556     vector<string> vec;
557     // TODO how to improve below
558     while(getline(ss,sub_str,' ')) 
559         vec.push_back(sub_str);
560    // return EvaluateInfixStringHelp(vec);
561     return EvaluateInfixStringHelp(vec, 0, vec.size() - 1);
562 }
563 
564 double EvaluateInfixString2(const string& infix_string) {
565     stringstream ss(infix_string);
566     string sub_str;
567     list<string> l;
568     while(getline(ss,sub_str,' ')) 
569         l.push_back(sub_str);
570     return EvaluateInfixStringHelp2(l);
571 }
572 double EvaluateInfixStringHelp2(list<string> &l) {
573     //递归出口,只有一个数字
574     if (l.size() == 1)    
575         return ConvertString2Num<double>(*(l.begin()));
576     
577     list<string> list_left, list_right; 
578     char op; //根的内容
579     
580     SplitList(l, list_left, list_right, op);
581 
582     switch(op) {
583         case '+':
584             return EvaluateInfixStringHelp2(list_left) +
585                    EvaluateInfixStringHelp2(list_right);
586             break;
587         case '-':
588             return EvaluateInfixStringHelp2(list_left) - 
589                    EvaluateInfixStringHelp2(list_right);
590             break;
591         case '*':
592             return EvaluateInfixStringHelp2(list_left) *
593                    EvaluateInfixStringHelp2(list_right);
594             break;
595         case '/':
596             return EvaluateInfixStringHelp2(list_left) /
597                    EvaluateInfixStringHelp2(list_right);
598             break;
599         default:
600             break;
601     }
602 
603 }
604 void SplitList(list<string> &l, list<string> &list_left, list<string> &list_right, char &op) {
605     assert(l.size() >= 3); //at least 3 + 2 using 3 space
606     bool visited = false;  //是否已经遇到过* /
607     stack<int> s; //s空表示在括号外部,每次入栈值+1
608     int sum = 0;  //sum = 0表示入的是第一个括号,如果该括号最后才被出栈,则证明有最外()需要去除
609     int pre_sum = -1//别忘了,因为*/ 是暂时人选,后面继续变化,但是如果最终选择,需要恢复其所有信息,包括最外括号信息
610     int pre_sum_candidate = -1;
611     char candidate_op;
612     bool left_flag = false;   //是否有最外括号要去掉
613     bool right_flag = false;
614     //从右向左扫描数组
615     list<string>::iterator iter, pos_iter, candidate_pos_iter;
616     pos_iter = candidate_pos_iter = --l.begin();
617 
618     for (iter = --l.end(); iter != --l.begin(); --iter) {
619         if (IsNum((*iter)))
620             continue;
621         switch((*iter)[0]) {
622             case ')':
623                 s.push(sum++);
624                 break;
625             case '(':
626                 pre_sum = s.top();
627                 s.pop();
628                 break;
629             case '+'case '-':
630                 if (s.empty()) {
631                     pos_iter = iter;
632                     op = (*iter)[0];
633                 }
634                 break;
635             case '*'case '/':
636                 if (s.empty() && !visited) {
637                     candidate_pos_iter = iter;
638                     candidate_op = (*iter)[0];
639                     visited = true;
640                     pre_sum_candidate = pre_sum;
641                 }
642                 break;
643             default:
644                 cout << "error operator" << endl;
645                 break;
646         }
647         if (pos_iter != --l.begin())  //已经遇到括号外面的+ -了结束 
648             break;
649     }
650 
651     if (pos_iter == --l.begin()) {
652         pos_iter = candidate_pos_iter;
653         op = candidate_op;
654         pre_sum = pre_sum_candidate;
655     }
656     
657     iter = pos_iter;
658     if (((*(++iter)))[0== '(' && (*(--l.end()))[0== ')' && pre_sum == 0)
659         right_flag = true;
660     sum = 0;
661     pre_sum = -1;
662     iter = pos_iter;
663     //破括号!否则所有的符号都在括号内,无法继续了
664     if ((*(l.begin()))[0== '(' && (*(--iter))[0== ')') {
665         for (iter = l.begin(); iter != pos_iter; iter++) {
666             if ((*iter)[0== '(')
667                 s.push(sum++);
668             if ((*iter)[0== ')') {
669                 pre_sum = s.top();
670                 s.pop();
671             }
672         }
673         if (pre_sum == 0)
674             left_flag = true;
675     }
676 
677     if (left_flag) { 
678         iter = pos_iter;
679         --iter;
680         list_left.splice(list_left.end(), l, ++l.begin(), iter);
681     } else {
682         list_left.splice(list_left.end(), l, l.begin(), pos_iter);
683     }
684 
685     iter = pos_iter;
686     if (right_flag) {
687         iter++;
688         iter++;
689         list_right.splice(list_right.end(), l, iter, --l.end());  
690     } else {
691         iter++;
692         list_right.splice(list_right.end(), l, iter, l.end());
693     }
694 }
695 
696 void CreateExpressionBinaryTree(const string& infix_string,
697                                 Tree &binary_tree) {
698     if (!binary_tree.IsEmpty())
699         binary_tree.DeleteBinaryTree(binary_tree.root());
700     
701     //string内容按" "分开后存到vec中
702     stringstream ss(infix_string);
703     string sub_str;
704     vector<string> vec;
705     while(getline(ss,sub_str,' ')) 
706         vec.push_back(sub_str);
707     binary_tree.set_root(CreateExpressionBinaryTreeHelp(vec));
708 }
709 
710 Node *  CreateExpressionBinaryTreeHelp(
711         const vector<string> &vec) {
712     //递归出口,只有一个数字
713     if (vec.size() == 1)    
714         return new Node(vec[0]);
715     vector<string> vec_left, vec_right;  
716     char op;
717     
718     SplitVec(vec, vec_left, vec_right, op);
719 
720     //不能 string(char) 从类型‘char’到类型‘const char*’的转换无效
721     string op_string;
722     op_string += op;
723     Node * pnode = new Node(op_string);
724     pnode->set_left(CreateExpressionBinaryTreeHelp(vec_left));
725     pnode->set_right(CreateExpressionBinaryTreeHelp(vec_right));
726     return pnode;
727 }
728 
729 
730 }   //end of namespace expression



posted @ 2009-08-30 18:29  阁子  阅读(3201)  评论(0编辑  收藏  举报