队列的定义
queue是STL容器中的一种,队列有队头和队尾,队列可以从两头弹出元素
#include <iostream>
#include <queue>
using namespace std;
int main()
{
//队列queue
//push/pop/front/back/empty
//push
queue<int> a;
for (int i = 0; i < 5; i ++)
{
a.push(i);//从队尾插入
}
//front/back
cout << a.front() << endl;//返回队头元素
cout << a.back() << endl;//返回队尾元素
a.pop();//把队头拿掉
cout << a.front() << endl;
a.pop();
cout << a.front() << endl;
cout << "清空一个数组:"<<endl;
queue<int> b;
for (int i = 0; i < 5 ; i ++)
{
b.push(i);
}
for (int i = 0; i < 5; i ++)
{
b.pop();
}
//empty
cout << b.empty() << endl;
//队列是无序的
queue<int> c;
c.push(9);
c.push(1);
c.push(2);
cout << c.front() << endl;
//队列里面装结构体
cout << "队列里面装结构体:" << endl;
//定义一个结构体
struct res
{
int x, y;
bool operator < (const res& t) const//结构体内必须定义小于号
{
return x < t.x;
}
};
queue<res> d;//定义一个结构体的队列
res p;
p.x = 1;
p.y = 2;
d.push(p);//将p这个结构体插到d这个队列中去
res q;
q.x = 4;
q.y = 3;
d.push(q);//将q这个结构体插入到d这个队列中去
cout << d.front().x << ' ' << d.front().y << endl;//输出队头
cout << d.back().x << ' ' << d.back().y << endl;//输出队尾
d.pop();//将队头删掉
cout << d.front().x << ' ' << d.front().y << endl;
cout << endl;
//优先队列priority_queue(大根堆)
priority_queue<int> m;//大根堆,堆顶为大根
//push/pop/top
//push
m.push(5);
m.push(1);
m.push(6);
m.push(2);
//top
cout << m.top() << endl;//输出最大值
//pop
m.pop();//删除堆顶
cout << m.top() << endl;
//大根堆里装结构体
struct ans
{
int v, w;
bool operator < (const ans& t) const //大根堆定义小于号
{
return v < t.v;
}
};
priority_queue<ans> n;
ans a1;
a1.v = 2;
a1.w = 1;
ans a2;
a2.v = 2;
a2.w = 0;
n.push(a1);
n.push(a2);
//先比较v,谁大谁堆顶
//v相同比较w,谁大谁堆顶
cout << n.top().v << ' ' << n.top().w << endl;
n.pop();//删除堆顶
cout << n.top().v << ' ' << n.top().w << endl;
cout << endl;
//优先队列priority_queue<int,vector<int>,greater<int>>(小根堆)
//push/top/pop
priority_queue<int, vector<int>, greater<int>> s;
//push
s.push(5);
s.push(1);
//top
cout << s.top() << endl;
//小根堆里装结构体
struct sum
{
int t1, t2;
bool operator > (const sum& t) const //小根堆定义大于号
{
return t1 > t.t1;
}
};
priority_queue<sum, vector<sum>, greater<sum>> k;
sum s1;
s1.t1 = 1;
s1.t2 = 5;
sum s2;
s2.t1 = 0;
s2.t2 = 9;
k.push(s1);
k.push(s2);
cout << k.top().t1 << ' ' << k.top().t2 << endl;
//pop
k.pop();
cout << k.top().t1 << ' ' << k.top().t2 << endl;
}
AcWing 829. 模拟队列
输入样例:
10
push 6
empty
query
pop
empty
push 3
push 4
pop
query
push 6
代码展示:
#include <iostream>
using namespace std;
const int N = 100010;
int q[N], hh = 0, tt = -1;//初始化队头队尾
int main()
{
cin.tie(0);
int m;
cin >> m;
while (m --)
{
string op;
cin >> op;
int x;
if (op == "push") cin >> x, q[++ tt] = x;//从队尾插入
if (op == "pop") hh ++;//队头弹出一个元素
if (op == "query") cout << q[hh] <<endl;
if (op == "empty") //判断队列是否为空
{
if (hh > tt) cout << "YES" << endl;
else cout << "NO" << endl;
}
}
return 0;
}
AcWing 154. 滑动窗口
输入样例:
8 3
1 3 -1 -3 5 3 6 7
q[]存储的是坐标(注意!!!)
a[]存储元素
hh为队头,tt为队尾
代码展示:
#include <iostream>
using namespace std;
const int N = 1000100;
int a[N], q[N], hh = 0, tt = -1;
int main()
{
int n, k;
cin >> n >> k;
for (int i = 0; i < n; i ++ ) scanf("%d",&a[i]);
for (int i = 0; i < n; i ++ )
{
if (hh <= tt && i - q[hh] + 1 > k) hh ++;
//当队列中所存储的下标大于k时,就将队头弹出
while (a[i] < a[q[tt]] && hh <= tt) tt --;
//当前插入的元素比队尾所指向的元素小的话,将队尾弹出
//队列中保持单调上升的趋势,不满足的,就把弹出
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 - q[hh] + 1 > k) hh ++;
while (hh <= tt && a[i] > a[q[tt]]) tt --;
q[++ tt] = i;
if (i >= k - 1) printf ("%d ",a[q[hh]]);
}
}
思路+解析:
以所给数据为例模拟窗口移动过程:
接下来是模拟队列变化过程(以最小值为例):
维持队列里面存储的下标所对应的元素的值是单调递增的