05-栈 stack
1. 栈的概念
栈: 只允许在一端进行数据插入和删除的线性表.
- 栈顶: 数据操作的一端
- 栈底: 栈的另外一端
- 进栈: 插入数据 push
- 出栈: 删除数据 pop
2. 栈的模拟实现
- 本质还是线性表,因此可以创建一个足够大的数组,充当栈结构
- 再定义一个变量n,用来记录栈中元素的个数,同时还可以标记栈顶的位置
#include <iostream>using namespace std;const int N = 1e5 + 10;// 创建栈
int stk[N], n;// 进栈 - 本质就是顺序表里面的尾插
void push(int x)
{stk[++n] = x;
}// 出栈 - 顺序表的尾删操作
void pop()
{n--;
}// 查询栈顶元素
int top()
{return stk[n];
}// 判断是否为空
bool empty()
{return n == 0;
}// 查询有效元素的个数
int size()
{return n;
}
3. STL -- stack
#include <iostream>
#include <stack>using namespace std;int main()
{stack<int> st;// 先讲 1~10 进栈for(int i = 1; i <= 10; i++){st.push(i);}while(st.size()) // !st.empty(){cout << st.top() << endl;st.pop();}return 0;
}
4. 算法习题
4.1. B3614 【模板】栈
B3614 【模板】栈 - 洛谷
#include <iostream>using namespace std;typedef unsigned long long LL;
const int N = 1e6 + 10;int top;
LL stk[N];int main()
{int T; cin >> T;while(T--){// 清空栈top = 0;int n; cin >> n;while(n--){string op; cin >> op;if(op == "push") // 入栈{LL x; cin >> x;stk[++top] = x;}else if(op == "pop") // 出栈{if(top == 0) cout << "Empty" << endl;else top--;}else if(op == "query") // 查询{if(top == 0) cout << "Anguei!" << endl;else cout << stk[top] << endl;}else // 栈的大小{cout << top << endl;}}}return 0;
}
4.2. 有效的括号
20. 有效的括号 - 力扣(LeetCode)
思路: 利用栈的特性来验证
class Solution
{
public:bool isValid(string s) {stack<char> st;for(auto ch : s){if(ch == '[' || ch == '(' || ch == '{'){st.push(ch);}else{if(st.empty()) return false;char left = st.top();if(ch == ')' && left != '(') return false;if(ch == ']' && left != '[') return false;if(ch == '}' && left != '{') return false;st.pop();}}return st.empty();}
};
4.3. P4387 【深基15.习9】验证栈序列
P4387 【深基15.习9】验证栈序列 - 洛谷
#include <iostream>
#include <stack>using namespace std;const int N = 1e5 + 10;int n;
int a[N], b[N];int main()
{int Q; cin >> Q;while(Q--){cin >> n;for(int i = 1; i <= n; i++) cin >> a[i];for(int i = 1; i <= n; i++) cin >> b[i];stack<int> st;int j = 1;for(int i = 1; i <= n; i++) // 让元素依次进栈{st.push(a[i]);while(j <= n && st.size() && st.top() == b[j]) // 栈中有元素才可以pop元素{// 出栈st.pop();j++;}}if(st.size()) cout << "No" << endl;else cout << "Yes" << endl;}return 0;
}
4.4. P1449 后缀表达式
P1449 后缀表达式 - 洛谷
#include <iostream>
#include <stack>using namespace std;int main()
{stack<int> st;char ch;int num = 0;while(cin >> ch){if(ch == '@') break;else if(ch >= '0' && ch <= '9'){num = num * 10 + ch - '0';}else if(ch == '.'){st.push(num);num = 0;}else // 遇到了操作符{int b = st.top(); st.pop();int a = st.top(); st.pop();// a ch bif(ch == '+') st.push(a + b);else if(ch == '-') st.push(a - b);else if(ch == '*') st.push(a * b);else st.push(a / b);}}cout << st.top() << endl;return 0;
}
4.5. P1241 括号序列
P1241 括号序列 - 洛谷
思路: 遍历字符串, 标记各个位置是否配对, 再为未配对区域进行配对(加入字符)即可.
#include <iostream>
#include <stack>using namespace std;const int N = 110;bool st[N]; // st[i] 标记是否已经匹配int main()
{string s; cin >> s;stack<int> stk; // 里面存的是左括号的下标for(int i = 0; i < s.size(); i++){char ch = s[i];if(ch == '[' || ch == '(') stk.push(i);else {// 右括号if(stk.empty()) continue;int t = stk.top();char left = s[t];if((left == '(' && ch == ')') || (left == '[' && ch == ']')){st[t] = st[i] = true;stk.pop();}}}// 还原字符串string ret = "";for(int i = 0; i < s.size(); i++){char ch = s[i];if(st[i]) ret += ch;else{if(ch == '('){ret += ch;ret += ')';}else if(ch == ')'){ret += '(';ret += ch;}else if(ch == '['){ret += ch;ret += ']';}else{ret += '[';ret += ch;}}}cout << ret << endl;return 0;
}