将符号字符串解析为表达式
给定一个由数字和基本算术运算运算符(+、-、*、/)组成的字符串str形式的表达式,任务是求解该表达式。请注意,此程序中使用的数字是个位数,不允许使用括号。
例子:
Input: str = “3/3+4*6-9”
Output: 16
Since (3 / 3) = 1 and (4 * 6) = 24.
So the overall expression becomes (1 + 24 – 9) = 16
Input: str = “9*5-4*5+9”
Output: 16
方法:创建一个 Stack 类来存储数字和运算符(都作为字符)。堆栈是一种有用的存储机制,因为在解析表达式时,需要经常访问最后存储的项目;堆栈是后进先出 (LIFO) 容器。
除了 Stack 类之外,还创建了一个名为 express(表达式的缩写)的类,表示整个算术表达式。此类的成员函数允许用户使用字符串形式的表达式初始化对象、解析表达式并返回结果算术值。
以下是算术表达式的解析方式。
一个指针从左边开始,并被迭代以查看每个字符。它可以是数字(通常是 0 到 9 之间的一位字符)或运算符(字符+、-、* 和 /)。
如果字符是数字,则将其压入堆栈。遇到的第一个运算符也被压入堆栈。诀窍是处理后续运算符。请注意,当前运算符无法执行,因为它后面的数字尚未被读取。找到一个运算符只是我们可以执行前一个运算符符的信号,它存储在堆栈中。也就是说,如果序列 2+3 在堆栈上,我们等到找到另一个运算符后再执行加法。
因此,只要当前字符是运算符(第一个除外),前一个数字(上例中的 3)和前一个运算符(+) 就会从堆栈中弹出,将它们放在变量 lastval 和 lastop 中。最后,弹出第一个数字 (2) 并对这两个数字进行算术运算(得到 5)。
但是,当遇到优先级高于 + 和 – 的 * 和 / 时,无法执行表达式。在表达式 3+4/2 中,在执行除法之前不能执行 +。因此,2 和 + 被放回堆栈,直到执行除法。
另一方面,如果当前运算符是 + 或 -,则可以执行前一个运算符。即表达式4-5+6遇到+时,执行-即可,6/2-3遇到-时,执行除法即可。表 10.1 显示了四种可能性。
Previous Operator | Current Operator | Example | Action |
---|---|---|---|
+ or – | * or / | 3+4/ | Push previous operator and previous number (+, 4) |
* or / | * or / | 9/3* | Execute previous operator, push result (3) |
+ or – | + or – | 6+3+ | Execute previous operator, push result (9) |
* or / | + or – | 8/2- | Execute previous operator, push result (4) |
下面是上述方法的实现:
CPP
// C++ implementation of the approach
#include
#include
using namespace std;
// Length of expressions in characters
const int LEN = 80;
// Size of the stack
const int MAX = 40;
class Stack {
private:
// Stack: array of characters
char st[MAX];
// Number at top of the stack
int top;
public:
Stack()
{
top = 0;
}
// Function to put a character in stack
void push(char var)
{
st[++top] = var;
}
// Function to return a character off stack
char pop()
{
return st[top--];
}
// Function to get the top of the stack
int gettop()
{
return top;
}
};
// Expression class
class Express {
private:
// Stack for analysis
Stack s;
// Pointer to input string
char* pStr;
// Length of the input string
int len;
public:
Express(char* ptr)
{
pStr = ptr;
len = strlen(pStr);
}
// Parse the input string
void parse();
// Evaluate the stack
int solve();
};
void Express::parse()
{
// Character from the input string
char ch;
// Last value
char lastval;
// Last operator
char lastop;
// For each input character
for (int j = 0; j < len; j++) {
ch = pStr[j];
// If it's a digit then save
// the numerical value
if (ch >= '0' && ch <= '9')
s.push(ch - '0');
// If it's an operator
else if (ch == '+' || ch == '-'
|| ch == '*' || ch == '/') {
// If it is the first operator
// then put it in the stack
if (s.gettop() == 1)
s.push(ch);
// Not the first operator
else {
lastval = s.pop();
lastop = s.pop();
// If it is either '*' or '/' and the
// last operator was either '+' or '-'
if ((ch == '*' || ch == '/')
&& (lastop == '+' || lastop == '-')) {
// Restore the last two pops
s.push(lastop);
s.push(lastval);
}
// In all the other cases
else {
// Perform the last operation
switch (lastop) {
// Push the result in the stack
case '+':
s.push(s.pop() + lastval);
break;
case '-':
s.push(s.pop() - lastval);
break;
case '*':
s.push(s.pop() * lastval);
break;
case '/':
s.push(s.pop() / lastval);
break;
default:
cout << "\nUnknown oper";
exit(1);
}
}
s.push(ch);
}
}
else {
cout << "\nUnknown input character";
exit(1);
}
}
}
int Express::solve()
{
// Remove the items from stack
char lastval;
while (s.gettop() > 1) {
lastval = s.pop();
switch (s.pop()) {
// Perform operation, push answer
case '+':
s.push(s.pop() + lastval);
break;
case '-':
s.push(s.pop() - lastval);
break;
case '*':
s.push(s.pop() * lastval);
break;
case '/':
s.push(s.pop() / lastval);
break;
default:
cout << "\nUnknown operator";
exit(1);
}
}
return int(s.pop());
}
// Driver code
int main()
{
char string[LEN] = "2+3*4/3-2";
// Make expression
Express* eptr = new Express(string);
// Parse it
eptr->parse();
// Solve the expression
cout << eptr->solve();
return 0;
}
4
时间复杂度:O(N)。
辅助空间:O(N)。