用数组实现栈与队列
用数组实现栈与队列思路很简单,清楚栈与队列的特性就可以理解了。
代码
#include <iostream>
using namespace std;
const int N = 100010;
//*****************************栈
//tt表示栈顶下标
int stk[N], tt;
//插入
stk[++tt] = x;
//弹出
tt--;
//判断栈为不为空
if (tt > 0)
//栈顶
stk[tt];
//*****************************队列
//在队尾插入元素,在队头弹出元素
int q[N], hh, tt = -1;
//插入
q[++tt] = x;
//弹出
hh++;
//判断队列是否为空
if (hh <= tt) not empty
else empty
//取出队头元素
q[hh];
单调栈
单调栈最常用的例子就是:
给定一个序列,找到一个数左边比这个数小且离这个数最近,如果不存在就输出-1
理解:
主要的重点在代码 while (tt && stk[tt] >= x) tt--; 中。
当栈顶元素小于大于等于x时就把栈顶元素删掉,不断循环直到tt == 0,或找到一个点,使得这个点小于x。其实这里栈就相当于是一个单调函数。
删掉栈顶元素:因为x在栈顶元素的右边,如果后面的数要找的话,那么会先找到x。
代码
#include <iostream>
using namespace std;
const int N = 100010;
int n;
int stk[N], tt;
int main()
{
cin >> n;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
while (tt && stk[tt] >= x) tt--;
if (tt) cout << stk[tt] << ' ';
else cout << -1 << ' ';
stk[++tt] = x;
}
return 0;
}
单调队列
单调队列最常见的应用就是:
求滑动窗口里面的最大值或最小值。
理解
单调队列的过程就是while (hh <= tt && a[q[tt]] >= a[i]) tt--;
在求窗口最小值的过程中,我们首先判断队列是否为空,然后判断队尾元素是否大于等于x。如果大于等于则删去(x能存活的时间最长,x在一天则队尾元素就派不上用场,可以删除),如果小于则保留(放在队尾,毕竟x的存活时间更长,可能x在后面的滑动窗口里就是最小值)。
注意的点:这里的队列存储的是数组的下标,判断队头是否滑出窗口也是用下标来判断。
代码
#include <iostream>
using namespace std;
const int N = 100010;
int n, k;
int a[N], q[N];
int main()
{
cin >> n >> k;
for (int i = 0; i < n; i++) cin >> a[i];
//求最小值
int 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) cout << a[q[hh]] << ' ';
}
cout << endl;
//求最大值
int 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) cout << a[q[hh]] << ' ';
}
return 0;
}