stack:后进先出,只能在栈顶操作
queue:先进先出,队尾插入push,队头删除pop
方法:
empty,size,push,pop
栈特有:top
队列特有:back,front
题目链接
class MinStack {
private:
stack<int> s;
stack<int> mins;
public:
/*
题目要求:常数时间内检索到最小元素的栈。
可以设置一个min来保存最小元素,但是如果这个最小的出栈了,那当前栈的min就要更新,还要重新去找,显然是不合理的
有一种想法:另设一个栈,来保存每次增加一个元素后,当前栈的最小
例如: 入栈:3,7,6,5,1
栈 保存min的栈
1 1
5 3
6 3
7 3
3 3
栈每出一个元素,对应的min栈也要出一个元素
*/
MinStack() {
}
void push(int val) {
s.push(val);
if(mins.empty()||mins.top()>val)//minstack是空栈或者,新入栈的元素小于当前top,push新入栈元素
mins.push(val);
else mins.push(mins.top());//否则,还要把top再push一次,要和stack一一对应
}
void pop() {
s.pop();
mins.pop();
}
int top() {
return s.top();
}
int getMin() {
return mins.top();
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(val);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
提到栈,就不得不提及逆波兰表达式
逆波兰表达式:
逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。
平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。
该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。
逆波兰表达式主要有以下两个优点:
- 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
- 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
#include<iostream>
#include<stack>
using namespace std;
#include<string>
#include<vector>
int evalRPN(vector<string>& tokens) {
stack<string> s;
for (auto x : tokens)
{
//x.size()==1是为了去除负数的情况
if (x.size() == 1 && (x[0] == '+' || x[0] == '-' || x[0] == '/' || x[0] == '*'))
{
int n1, n2;//注意n1,n2的顺序
// 1,2,/ 应该让n2先获取 这样才是 1 / 2
n2 = stoi(s.top());
s.pop();
n1 = stoi(s.top());
s.pop();
switch (x[0])
{
case '+':n1 += n2; break;
case '-':n1 -= n2; break;
case '*':n1 *= n2; break;
case '/':n1 /= n2; break;
}
s.push(to_string(n1));
}
else
s.push(x);
cout << s.top() << endl;;
}
return stoi(s.top());
}
int main()
{
vector<string> tokens = {"4", "13", "5", "/", "+"};
evalRPN(tokens);
}
栈模拟实现
#pragma once
#include<vector>
namespace gyx
{
//用vector作为stack的底层数据结构
template<class T,class Container=std::vector<T>>
class stack
{
private:
Container c;
public:
stack()
{}
void push(const T& val){ c.push_back(val); }
void pop()
{
if (c.empty())
return;
c.pop_back();
}
T& top(){ return c.back(); }
const T& top()const{ return c.back(); }
size_t size()const{ return c.size(); }
bool empty()const{ return c.empty(); }
};
}
队列模拟实现
#pragma once
#include<list>
namespace gyx
{
template<class T,class Container=std::list<T>>
class queue
{
private:
std::list<T> q;
public:
queue(){}
void push(const T& val){ q.push_back(val); }
void pop()
{
if (q.empty())return;
q.pop_front();
}
T& front(){ return q.front(); }
T& back(){ return q.back(); }
const T& front()const{ q.front(); }
const T& back()const{ q.back(); }
bool empty(){ return q.empty(); }
};
}
测试:
#include"Stack.h"
#include<iostream>
using namespace gyx;
void test_stack()
{
stack<int> s;
for (int i = 0; i < 10;i++)
s.push(i);
//for (int i = 0; i < s.size(); i++)//这样遍历对吗?不对,因为size是变化的
//{
// std::cout << s.top()<<" ";
// s.pop();
//}
while (!s.empty())
{
std::cout << s.top() << " ";
s.pop();
}
}
#include"Queue.h"
void test_queue()
{
queue<int> q;
for (int i = 0; i < 10; i++)
q.push(i);
while (!q.empty())
{
std::cout << q.front() << " " << q.back() << '\n';
q.pop();
}
}
int main()
{
test_stack();
test_queue();
return 0;
}