代码
namespace bit {
template<class T,class Container=deque<T>>
class Stack {
public:
void push_back(const T& temp) {
_con.push_back(temp);
}
void pop_back() {
_con.pop_back();
}
T& top() {//
return *(_con.end()-1);//这里不要用--会出问题的
}
const T& top() const {
return *(_con.end()-1);
}
size_t size() const{
return _con.size();
}
bool empty()const {
return _con.empty();
}
private:
Container _con;
};
}
//queue的模拟实现只需要把top和pop的顺序改一下就好了
其实stack和queue的模拟实现还是挺简单的,就是复用其他容器的成员
问题
Container=deque<T>是什么
deque是一个集合了vector和List优点(以及缺点)的容器,成员也大差不差,这里作为定义stack的默认值,也可以自行定义stack中的元素用什么来存储,见下面的例子
bit::Stack < list<int>> stack;//在stack中用deque来存储list
bit::Stack <int> stack;//用deque来存储int
bit::Stack<int, vector<int>> stack;//不使用deque而是指定用vector来存储int
stack是不是用不了范围for?
没有定义begin和end肯定是不行的,栈和队列本身的性质就要求不能链式访问,必须的删掉头一个才能访问下一个
练习题
逆波兰表达式求值
https://leetcode.cn/problems/evaluate-reverse-polish-notation/
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> mystack;
for (int i = 0; i < tokens.size(); i++) {
if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {
int temp2 = mystack.top();
mystack.pop();
int temp1 = mystack.top();
mystack.pop();
if (tokens[i] == "+") {
mystack.push(temp1 + temp2);
}
if (tokens[i] == "-") {
mystack.push(temp1 - temp2);
}
if (tokens[i] == "*") {
mystack.push(temp1 * temp2);
}
if (tokens[i] == "/") {
mystack.push(temp1 / temp2);
}
continue;
}
mystack.push(stoi(tokens[i]));
}
return mystack.top();
}
};
题意理解花时间,简单概括就是遇到运算符的时候对符号前面的两数运算,再回到数组
那已经很清晰了:
把数组中的字符一个个插入到栈里面,发现要插入的是运算符的时候就直接从栈里面出两个数进行相应的运算再推回栈里面,由于没办法把字符的运算符直接变成有实际效应的运算符,所以只能用四个条件判断来运算。
最后剩下的那个数字就是答案,循环的次数一定和给定数组中的字符串数量相同(推一下就知道了)
最小栈
https://leetcode.cn/problems/min-stack/
class MinStack {
public:
MinStack() {
int _size = 0;
}
void push(int val) {
container.push_back(val);
if (_size == 0) {
all_min.push_back(val);
_size++;
return;
}
for (auto i = all_min.begin(); i != all_min.end(); i++) {
if (val > *i) {
all_min.insert(i, val);
_size++;
return;
}
}
all_min.push_back(val);
_size++;
}
void pop() {
int temp = top();
container.pop_back();
for (auto i = all_min.begin(); i != all_min.end();i++) {
if (*i == temp) {
i=all_min.erase(i);//迭代器失效问题!!!
if (i == all_min.end()) {
_size--;
return;
}
}
}
_size--;
}
int top() {
return *(container.end()-1);
}
int getMin() {
int min = *(all_min.end()-1);
return min;
}
int _size = 0;
vector<int> all_min;
vector<int> container;
};
说实话这是很笨的写法(因为直接变成了vector的用法运用了)可以参考标准的题解,也就是用双栈或者一个栈来解决,这里只是总结一下经验
一开始想到用一个栈来解决,发现当pop的时候,Min值应该刷新,那要怎么找到前一个min值呢?就算定义了一个min的prev,要是再Pop一次怎么找到上上个min值?
所以就想到干脆用个vector来存所有的值,然后每次Push时保证顺序,然后pop的时候删除对应值就好了
栈的弹出压入序列
class Solution {
public:
stack<int> pushstack;
queue<int> popqueue;
bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {
for (auto i : popV) {
popqueue.push(i);
}
for (auto i : pushV) {
pushstack.push(i);
while (!pushstack.empty()&&pushstack.top()==popqueue.front() ) {
pushstack.pop();
popqueue.pop();
}
}
return pushstack.empty();
}
};
这道题犯了没想清楚就开始敲代码的错,然后写的过程中改了又改,第一个通过的版本也是惨不忍睹,加了一堆的判断条件和多了个冗余的循环
其实大思路挺简单的,草稿纸上推演几遍就发现和消消乐一样,pushV的后头和popV的前头相同的时候就消掉,pushv是边插入边和PopV匹配相消的。所以就想到用一个stack(头是数组尾)来存pushV,用一个queue(头就是数组头)来存popV。直接用两个vector应该也是可以的。
677

被折叠的 条评论
为什么被折叠?



