在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
关于字符串表达式求值,应该是程序猿们机试或者面试时候常见问题之一,昨天参加国内某IT的机试,压轴便为此题,今天抽空对其进行了研究。 算术表达式中最常见的表示法形式有 中缀、前缀和 后缀表示法。中缀表示法是书写表达式的常见方式,而前缀和后缀表示法主要用于计算机科学领域。 中缀表示法 Syntax: operand1 operator operand2 Example: (A+B)*C-D/(E+F)
前缀表示法 Syntax : operator operand1 operand2 Example : -*+ABC/D+EF
后缀表示法 Syntax : operand1 operand2 operator Example : AB+C*DEF+/-
字符串表达式求值,一般来说采用如下方式: 要把表达式从中缀表达式的形式转换成用后缀表示法表示的等价表达式,必须了解操作符的优先级和结合性。 优先级或者说操作符的强度决定求值顺序;优先级高的操作符比优先级低的操作符先求值。 如果所有操作符优先级一样,那么求值顺序就取决于它们的 结合性。操作符的结合性定义了相同优先级操作符组合的顺序(从右至左或从左至右)。 Left associativity : A+B+C = (A+B)+C
Right associativity : A^B^C = A^(B^C)
转换过程包括用下面的算法读入中缀表达式的操作数、操作符和括号:
二. 后缀表达式求值 对后缀表达式求值比直接对中缀表达式求值简单。在后缀表达式中,不需要括号,而且操作符的优先级也不再起作用了。您可以用如下算法对后缀表达式求值:
好了,基本思路讨论完毕,我们开始动手写代码,此段代码假设表达式中的预算符只包括四大基本运算符+、-、*、/,为了简化代码,我们也假设表达式中的数字只包括1-9。 函数getPostfixExp用来将一个中缀表达式转换为后缀表达式(也就是逆波兰式). string getPostfixExp(string& infix) { stack<char> operator_stack; string postfix; for (auto p : infix) { if (isOperator(p)) { while (!operator_stack.empty() && isOperator(operator_stack.top()) && priority(operator_stack.top()) >= priority(p)) { postfix.push_back(operator_stack.top()); postfix.push_back(' '); operator_stack.pop(); } operator_stack.push(p); } else if (p == '(') { operator_stack.push(p); } else if (p == ')') { while (operator_stack.top() != '(') { postfix.push_back(operator_stack.top()); postfix.push_back(' '); operator_stack.pop(); } operator_stack.pop(); } else { postfix.push_back(p); postfix.push_back(' '); } } while (!operator_stack.empty()) { postfix.push_back(operator_stack.top()); postfix.push_back(' '); operator_stack.pop(); } postfix.pop_back(); return postfix; } 其中isOperator函数如下: bool isOperator(char ch) { switch(ch) { case'+': case'-': case'*': case'/': return true; default: return false; } } 其中的priority函数如下: int priority(char a) { int temp; if (a == '*' || a == '/') temp = 2; else if (a == '+' || a == '-') temp = 1; return temp; } 得到了后缀表达式,开始我们的求值之旅吧! int postfixCalculate(string& postfix) { int first, second; stack<int> num_stack; for (auto p : postfix) { switch (p) { //if the item is an operator (+, -, *, or /) then // pop two numbers off the stack // make a calculation: the second number // popped-operator-first number // push the result on the stack case '*': getTwoNums(num_stack, first, second); num_stack.push(first * second); break; case '/': getTwoNums(num_stack, first, second); num_stack.push(first / second); break; case '+': getTwoNums(num_stack, first, second); num_stack.push(first + second); break; case '-': getTwoNums(num_stack, first, second); num_stack.push(first - second); break; case ' ': break; // if the item is a number push it on the stack default: num_stack.push(p - '0'); break; } } int result = num_stack.top(); num_stack.pop(); return result; } 其中getTwoNums函数如下: void getTwoNums(stack<int>& num_stack, int& first, int& second) { second = num_stack.top(); num_stack.pop(); first = num_stack.top(); num_stack.pop(); } 好了,全部的代码结束了,写个main函数试试吧! int main() { string infix; cin >> infix; string postfix = getPostfixExp(infix); cout << postfix << endl; cout << postfixCalculate(postfix) << endl; system("PAUSE"); return 0; } 写在最后的话: 字符串表达式求值方法很多,本文中利用stack结合优先级的方式,解决了这个问题。其他的方法,有表达式树的方式,编译原理的书上有讲解,大家可以结合原理,自己动手实现生成表达式树的代码,然后求值就变得so easy了,当然也有与上面两者迥然不同的方式,大家举一反三,多研究! |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论