简介
如果理解了 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 0
s.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);
else
nums.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;
// priority
int 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);
else
nums.push(x / y);
}
int calc() {
// number stack
stack<int> nums;
// operator stack
stack<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;
}