一、我们首先要了解栈的概念 在 c++中有着 STL 的存在可以方便我们做很多事,而 栈(stack)就是其中的一部分,简单的说栈就是一种 先进后出 的数据机构
栈的读入操作
// add insert
int x;
cin>>x;
stk[++tt] = x; // 我这里是把栈的下标从 1 开始 用来与队列进行区别
// 这样我们就已经把 x 读入到了我们的模拟栈中
栈的弹出操作
// remove
tt--;//这样就已经把队头的元素弹出了
这道题来自于AcWing第830题 也是有关单调栈的应用
这个是题解
#include <iostream>
using namespace std;
const int N = 1e5 +10;
int stk[N],tt;
int a[N];
int main(void)
{
int n;
cin>>n;
for(int i = 0;i<n;i++)
{
while(tt && stk[tt] > a[i]) tt--; // 这里会遍历数组里面的元素 把大于该值的数弹出
// 因为题意里面找的是第一位小于 a[i] 的值 如果
// 如果上一个值是大于 a[i] 的话那么接下来的值都
// 不会选择该值
if(!tt) cout<<"-1";
stk[++tt] = x;
}
}
下面来模拟队列,队列也是 STL 中的一个容器,他和栈的区别是先进先出,类似于水管一样,
也就是从队尾进入,从对头弹出
队列的读入操作
// add
hh = 0,tt = -1;// 这里我们将队列的下标设置为从一开始 与 栈 进行分开
int x;
cin>>x;
q[++tt] = x;// 从队尾插进了元素
队列的弹出操作
// remove
hh++;
这道题来自于AcWing第154题的滑动窗口问题
下面是题解
#include <iostream>
using namespace std;
const int N = 1e6 +10;
int q[N];
int a[N];
int hh,tt = -1;
int main(void)
{
int n,k;
cin>>n>>k;// n 代表数组长度 k 代表窗口长度
for(int i = 0;i<n;i++) cin>>a[i];
for(int i = 0;i < n;i++)
{
if(hh <= tt && i - k + 1>q[hh]) hh++;
while(hh <= tt && a[q[tt]] >= a[i]) tt--; // 这里是把所有大于 a[i] 的元素都弹了出去
//因为当队列中的最后进来的如果比前面的都
//小的话,前面的所有数值就都会用不到,所
//以把没用的元素都弹了出去,下面求大值的
//时候也是一个道理
q[++tt] = i;
if (i >= k - 1) printf("%d ", a[q[hh]]);
}
puts("");
hh=0,tt= -1;
for(int i = 0;i<n;i++)
{
if(hh <= tt && i-k+1>q[hh]) hh++;
while(hh <= tt && a[q[tt]] <= a[i]) tt--;
q[++tt] = i;
if (i >= k - 1) printf("%d ", a[q[hh]]);
}
cout<<endl;
}
有些人可能会有疑惑,明明可以用STL,我们为什么又要费心思去模拟他呢,这是因为,模拟STL可以省出很多时间,优化程序的效率,这一点在做算法题目的时候尤为重要