简介
如果理解了 vector,再学习接下来的栈和队列就会比较轻松。
STL 栈 ( std::stack ) 是一种后进先出 (Last In, First Out) 的容器适配器,仅支持查询或删除最后一个加入的元素(栈顶元素),不支持随机访问,且为了保证数据的严格有序性,不支持迭代器。
概念不好理解,但是总结出 stack 重要的 3 个方法,其实就对应着简单的数组操作。
push: 在数组末尾插入元素top: 获取数组末尾的元素pop: 删除末尾的元素
为了帮助理解,可以用 vector 模拟栈的行为。
#include <iostream>#include <vector>using namespace std;template <typename T>class stack {private:vector<int> data;public:void push(T value) {data.push_back(value);}T top() {return data.back();}void pop() {data.pop_back();}bool empty() {return data.size() == 0;}};int main() {stack<int> s;for (int i = 0; i < 5; ++i) {s.push(i);}while (!s.empty()) {cout << s.top() << ' '; // Output: 4 3 2 1 0s.pop();}return 0;}
使用
导入 <stack> 头文件,体验一下 STL 提供的栈:(其实和自己写的也没什么区别)
#include <iostream>#include <vector>#include <stack>using namespace std;int main() {stack<int> s;for (int i = 0; i < 5; ++i) {s.push(i);}while (!s.empty()) {cout << s.top() << ' ';s.pop();}return 0;}
综合案例
利用 逆波兰表达式 求解表达式
#include <iostream>#include <stack>#include <string>#include <vector>using namespace std;void calc(stack<int> &nums, stack<char> &ops) {int y = nums.top();nums.pop();int x = nums.top();nums.pop();char op = ops.top();ops.pop();if (op == '+')nums.push(x + y);else if (op == '-')nums.push(x - y);else if (op == '*')nums.push(x * y);elsenums.push(x / y);}// 运算符优先级int p(char op) {if (op == '*' || op == '/') return 1;return 0; // + -}int main() {// string s = "9 + (3 - 1) * 3 + 10 / 2";string s = "1+(2*3-6/4*(2-1))*5";stack<int> nums;stack<char> ops;int i = 0, n = s.size();while (i < n) {if (s[i] == ' ') {++i;continue;}if (isdigit(s[i])) {int num = s[i++] - '0';while (i < n && isdigit(s[i])) {num = num * 10 + s[i++] - '0';}nums.push(num);} else if (s[i] == '(') {ops.push(s[i++]);} else if (s[i] == ')') {while (ops.top() != '(') {calc(nums, ops);}ops.pop(); // pop '('++i;} else {if (ops.empty() || ops.top() == '(') {ops.push(s[i++]);} else {while (!ops.empty() && ops.top() != '(' && p(s[i]) <= p(ops.top())) {calc(nums, ops);}ops.push(s[i++]);}}}while (!ops.empty()) {calc(nums, ops);}cout << nums.top() << endl;return 0;}
思路二:递归处理括号
#include <bits/stdc++.h>using namespace std;// string s = "9+(3-1)*3+10/2";char s[1000];int i = 0, len;// priorityint level(char op) {if (op == '*' || op == '/') return 2;return 1;}void pop(stack<int> &nums, stack<char> &ops) {int y = nums.top();nums.pop();int x = nums.top();nums.pop();char op = ops.top();ops.pop();if (op == '+')nums.push(x + y);else if (op == '-')nums.push(x - y);else if (op == '*')nums.push(x * y);elsenums.push(x / y);}int calc() {// number stackstack<int> nums;// operator stackstack<char> ops;while (i < len && s[i] != ')') {if (isdigit(s[i])) {int num = s[i] - '0';while (isdigit(s[++i])) {num = num * 10 + s[i] - '0';}nums.push(num);} else if (s[i] == '(') {++i; // skip '('int sub = calc();nums.push(sub);++i; // skip ')'} else {while (!ops.empty() && level(s[i]) <= level(ops.top()))pop(nums, ops);ops.push(s[i]);++i; // skip current operator}}while (!ops.empty())pop(nums, ops);return nums.top();}int main() {cin >> s;len = strlen(s);cout << calc() << endl;return 0;}
