题目:
Basic Calculator:
Implement a basic calculator to evaluate a simple expression string.
The expression string may contain open (
and closing parentheses )
, the plus +
or minus sign -
, non-negative integers and empty spaces
.
思考:
1、首先分析题意,题目要求计算表达式值,首先想到的就是使用栈存储表达式,可先通过处理运算符将原表达式转化为后缀式,进而通过优先级计算后缀式,得到结果
2、但是仔细分析,可以发现,本题不需要将原式转化为后缀式求解。表达式中只包含非负整数,括号,+,-,以及空格。并不存在运算优先级的问题,只需要处理括号即可。
具体思路:
建立两个栈,分别为char,int,存储表达式中的运算符,和数字。用字符串s存储表达式,s尾部添加'#',表示结束,从头开始扫描s[i]:
- s[i]为' ',不作操作。
- s[i]为'(',进栈。
- s[i]为'+','-',判断运算符栈顶是否为空,或是否为'(',若不是则将数字栈的前两个元素弹出,将运算符栈弹出,进行运算,运算结果入栈,s[i]入栈。
- s[i]为')',将'('前的运算符弹出计算。
- s[i]为数字,将下一个运算符前的数字一同计算,结果压入栈。
- s[i]为'#',判断运算符栈是否为空,不为空,再弹栈进行计算,得到结果。
代码:
1 #include2 #include 3 #include <string> 4 using namespace std; 5 6 class Solution 7 { 8 public: 9 int calculate(string s) 10 { 11 stack<int> numbers; 12 stack<char> ops; 13 s.push_back('#'); //插入终止符'#' 14 for (int i = 0;i < s.length();i++) //依次扫描字符串s 15 { 16 switch (s[i]) 17 { 18 case ' ': 19 break; 20 case '(': 21 ops.push(s[i]); 22 break; 23 case ')': 24 while (ops.top() != '(') 25 { 26 int num_1, num_2; 27 char temp_op; 28 num_2 = numbers.top(); 29 numbers.pop(); 30 num_1 = numbers.top(); 31 numbers.pop(); 32 temp_op = ops.top(); 33 ops.pop(); 34 numbers.push(calculating(num_1, num_2, temp_op)); 35 } 36 ops.pop(); 37 break; 38 case '#': 39 if (!ops.empty()) 40 { 41 int num_1, num_2; 42 char temp_op; 43 num_2 = numbers.top(); 44 numbers.pop(); 45 num_1 = numbers.top(); 46 numbers.pop(); 47 temp_op = ops.top(); 48 ops.pop(); 49 numbers.push(calculating(num_1, num_2, temp_op)); 50 }; 51 break; 52 case '+': 53 case '-': 54 if (!ops.empty()) 55 { 56 if (ops.top() != '(') 57 { 58 int num_1, num_2; 59 char temp_op; 60 num_2 = numbers.top(); 61 numbers.pop(); 62 num_1 = numbers.top(); 63 numbers.pop(); 64 temp_op = ops.top(); 65 ops.pop(); 66 numbers.push(calculating(num_1, num_2, temp_op)); 67 } 68 } 69 ops.push(s[i]); 70 break; 71 default: //处理s[i]为数字的情况 72 int temp_answer = s[i] - '0'; 73 while (isDigit(s[i + 1])) 74 { 75 temp_answer = temp_answer * 10 + s[++i] - '0'; 76 } 77 numbers.push(temp_answer); 78 break; 79 } 80 } 81 return numbers.top(); 82 } 83 bool isDigit(char a) //判断字符是否为'0'-'9' 84 { 85 if (a >= '0' && a <= '9') 86 { 87 return true; 88 } 89 else 90 { 91 return false; 92 } 93 } 94 int calculating(int num1, int num2, char op) //加减计算 95 { 96 switch (op) 97 { 98 case '+': 99 return num1 + num2; 100 break; 101 default: 102 return num1 - num2; 103 break; 104 } 105 } 106 }; 107 108 int main() 109 { 110 Solution solution; 111 string s; 112 cin >> s; 113 cout << solution.calculate(s) << endl; 114 return 0; 115 }
进一步思考,当s结束时,需要再次判断数字栈是否为空,较为麻烦,可以在运算符栈先压入'(',且在字符串s后加')',则当s[i]为最后的')'时,可将运算符栈最底端'('之前的运算符都弹出计算,代码更加清晰简短。
代码如下:
1 #include2 #include 3 #include <string> 4 using namespace std; 5 6 7 8 9 class Solution 10 { 11 public: 12 int calculate(string s) 13 { 14 stack<int> numbers; 15 stack<char> ops; 16 ops.push('('); 17 s.push_back(')'); 18 for (int i = 0; i < s.length(); i++) 19 { 20 switch (s[i]) 21 { 22 case ' ': 23 break; 24 case '(': 25 ops.push(s[i]); 26 break; 27 case ')': 28 while (ops.top() != '(') 29 { 30 int num_1, num_2; 31 char temp_op; 32 num_2 = numbers.top(); 33 numbers.pop(); 34 num_1 = numbers.top(); 35 numbers.pop(); 36 temp_op = ops.top(); 37 ops.pop(); 38 numbers.push(calculating(num_1, num_2, temp_op)); 39 } 40 ops.pop(); 41 break; 42 case '+': 43 case '-': 44 if (!ops.empty() && ops.top() != '(') 45 { 46 int num_1, num_2; 47 char temp_op; 48 num_2 = numbers.top(); 49 numbers.pop(); 50 num_1 = numbers.top(); 51 numbers.pop(); 52 temp_op = ops.top(); 53 ops.pop(); 54 numbers.push(calculating(num_1, num_2, temp_op)); 55 } 56 ops.push(s[i]); 57 break; 58 default: 59 int temp_answer = s[i] - '0'; 60 while (isDigit(s[i + 1])) 61 { 62 temp_answer = temp_answer * 10 + s[++i] - '0'; 63 } 64 numbers.push(temp_answer); 65 break; 66 } 67 } 68 return numbers.top(); 69 } 70 bool isDigit(char a) 71 { 72 if (a >= '0' && a <= '9') 73 { 74 return true; 75 } 76 else 77 { 78 return false; 79 } 80 } 81 int calculating(int num1, int num2, char op) 82 { 83 switch (op) 84 { 85 case '+': 86 return num1 + num2; 87 break; 88 default: 89 return num1 - num2; 90 break; 91 } 92 } 93 }; 94 95 96 int main() 97 { 98 Solution solution; 99 string s; 100 cin >> s; 101 cout << solution.calculate(s) << endl; 102 return 0; 103 }
总结:
这个题目较为简单,只包含'+','-',' ','(',')',无需求后缀式,可简化程序。此算法只进行了一次扫描,时间复杂度为o(n),使用两个栈存储,空间复杂度为o(n),但此方法缺点是可扩展性较差,只适用于这个题目。
此博客中的内容均为原创或来自网络,不用做任何商业用途。欢迎与我交流学习,我的邮箱是[email protected]