代码随想录栈和队列专题二刷复盘day17
-
栈和队列理论基础
-
队列是先进先出,栈是先进后出
-
栈和队列是STL里面的两个数据结构
-
三个最为普遍的STL版本
-
1.HP STL其他版本的C++ STL,一般是以HP STL为蓝本实现出来的,HP STL是C++ STL的第一个实现版本,且开放源代码
-
2.P.J.Plauger STL 由P.J.Plauger参照HP STL实现出来的,被Visual C++编译器所采用,不是开源的。
-
3.SGI STL 由Silicon Graphics Computer Systems公司参照HP STL实现,被Linux的C++编译器GCC所采用,SGI STL是开源软件,源码可读性甚高。
-
-
-
栈提供push和pop等等接口,所有元素必须符合先进后出规则,所以栈不提供走访功能,也不能提供迭代器,不像是set或者map提供迭代器来遍历所有元素。栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(也就是说我们可以控制使用哪种容器来实现栈的功能)。所以STL中栈往往不被归类为容器,而被归类为container adapter(容器适配器)
-
栈的底层实现可以是vector,deque,list都是可以的,主要就是数组和链表的底层实现。常用的SGI STL,如果没有指定底层实现的化,默认是以deque为缺省情况下栈的底层结构,也可以指定vector为栈的底层实现
-
队列中先进先出的数据结构,同样不允许有遍历行为,不提供迭代器,SGI STL中队列一样是以deque为缺省情况下的底部结构,也可以指定list为其底层实现,所以STL队列也不被归类为容器,而被归类为container adapter(容器适配器)
-
232.用栈实现队列
232. 用栈实现队列 - 力扣(LeetCode)
1.双栈实现队列:在push数据的时候,只要数据放进输入栈就可以,但是在pop的时候,输出站如果为空,就把进栈数据全部导入,再从栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了
class MyQueue {
public:stack<int> stIn;stack<int> stOut;MyQueue() {}// 将元素x推到队列的末尾void push(int x) {stIn.push(x);}// 从队列的开头移除并返回元素int pop() {if(stOut.empty()) {while(!stIn.empty()) {stOut.push(stIn.top());stIn.pop();}}int result = stOut.top();stOut.pop();return result;}// 返回队列开头的元素int peek() {int res = this->pop();stOut.push(res);return res;}// 判断队列是否为空bool empty() {return stIn.empty() && stOut.empty();}
};/*** Your MyQueue object will be instantiated and called as such:* MyQueue* obj = new MyQueue();* obj->push(x);* int param_2 = obj->pop();* int param_3 = obj->peek();* bool param_4 = obj->empty();*/
225.用队列实现栈
225. 用队列实现栈 - 力扣(LeetCode)
1.用两个队列实现:用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用,把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1
class MyStack {
public:queue<int> que1;queue<int> que2; // 辅助队列,用来备份/** Initialize your data structure here. */MyStack() {}/** Push element x onto stack. */void push(int x) {que1.push(x);}/** Removes the element on top of the stack and returns that element. */int pop() {int size = que1.size();size--;while(size--) {// 将que1 导入que2,但要留下最后一个元素que2.push(que1.front());que1.pop();}int result = que1.front(); // 留下的最后一个元素就是要返回的值que1.pop();que1 = que2; // 再将que2赋值给que1while(!que2.empty()) { // 清空que2que2.pop();}return result;}/** Get the top element. */int top() {return que1.back();}/** Returns whether the stack is empty. */bool empty() {return que1.empty();}
};/*** Your MyStack object will be instantiated and called as such:* MyStack* obj = new MyStack();* obj->push(x);* int param_2 = obj->pop();* int param_3 = obj->top();* bool param_4 = obj->empty();*/
2.一个队列模拟栈:一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外)重新添加到队列尾部,此时在去弹出元素就是栈的顺序了
class MyStack {
public:queue<int> que;/** Initialize your data structure here. */MyStack() {}/** Push element x onto stack. */void push(int x) {que.push(x);}/** Removes the element on top of the stack and returns that element. */int pop() {int size = que.size();size--;while(size--) {que.push(que.front());que.pop();}int result = que.front();que.pop();return result;}/** Get the top element. */int top() {return que.back();}/** Returns whether the stack is empty. */bool empty() {return que.empty();}
};/*** Your MyStack object will be instantiated and called as such:* MyStack* obj = new MyStack();* obj->push(x);* int param_2 = obj->pop();* int param_3 = obj->top();* bool param_4 = obj->empty();*/
20.有效的括号
20. 有效的括号 - 力扣(LeetCode)
-
本题一共有三种情况
-
字符串里左括号多余了
-
字符串没有括号多余,但是出现不匹配的情况
-
字符串右括号多余了
-
1.栈的拿手好戏:如果遇到左括号就在栈里存入对应的右括号,如果匹配的时候发现栈为空或者元素不匹配的情况就直接返回false。最后如果栈不为空的情况,也返回false
class Solution {
public:bool isValid(string s) {if(s.size() % 2 != 0) return false;stack<char> st;for(int i = 0; i < s.size(); i++) {if(s[i] == '(') st.push(')');else if(s[i] == '[') st.push(']');else if(s[i] == '{') st.push('}');else if(st.empty() || s[i] != st.top()) return false;else st.pop();}return st.empty();}
};
1047.删除字符串中的所有相邻重复项
1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)
1.栈的拿手好戏:遍历整个字符串,如果栈为空或者元素不匹配,就把元素存入栈中,如果元素匹配,就弹出栈的匹配元素,最后将栈输出,并反转整个结果
class Solution {
public:string removeDuplicates(string s) {stack<char> st;for(int i = 0; i < s.size(); i++) {if(st.empty() || s[i] != st.top()) {st.push(s[i]);} else {st.pop();}}string result = "";while(!st.empty()) {result += st.top();st.pop();}reverse(result.begin(), result.end());return result;}
};
150.逆波兰表达式
150. 逆波兰表达式求值 - 力扣(LeetCode)
1.栈的最后表演:和删除字符串中的所有相邻重复项类似:遇到运算符就把栈的头两个元素进行运算然后存入栈中,最后得出结果
class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> st;for(int i = 0; i < tokens.size(); i++) {if(tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {int num1 = st.top();st.pop();int num2 = st.top();st.pop();if(tokens[i] == "+") st.push(num2 + num1);if(tokens[i] == "-") st.push(num2 - num1);if(tokens[i] == "*") st.push(num2 * num1);if(tokens[i] == "/") st.push(num2 / num1);} else {st.push(stoi(tokens[i]));}}int result = st.top();st.pop();return result;}
};