06-队列
1. 队列的概念
队列: 一端允许插入, 另一端允许删除的线性表.
- 队尾: 允许插入的一端
- 队头: 允许删除的一端
2. 队列的模拟实现
- 变量h标记队头元素的前一个位置;
- 变量t标记队尾元素的位置。
- 左开右闭
#include <iostream>using namespace std;const int N = 1e5 + 10;// 创建
int q[N], h, t;// 入队
void push(int x)
{q[++t] = x;
}// 出队
void pop()
{h++;
}// 查询队头元素
int front()
{return q[h + 1];
}// 查询队尾元素
int back()
{return q[t];
}// 判断是否为空
bool empty()
{return h == t;
}// 有效元素的个数
int size()
{return t - h;
}
3. STL -- queue
#include <iostream>
#include <queue>using namespace std;typedef pair<int, int> PII;int main()
{// 测试 queuequeue<PII> q;for(int i = 1; i <= 10; i++){q.push({i, i * 10});}while(q.size()) // while(!q.empty()){auto t = q.front();q.pop();cout << t.first << " " << t.second << endl;}return 0;
}
4. 算法习题
4.1. B3616 【模板】队列
B3616 【模板】队列 - 洛谷
#include <iostream>using namespace std;const int N = 1e4 + 10;int q[N], h, t;int main()
{int n; cin >> n;while(n--){int op, x;cin >> op;if(op == 1) // 进队{cin >> x;q[t++] = x;}else if(op == 2) // 出队{if(h == t) cout << "ERR_CANNOT_POP" << endl;else h++;}else if(op == 3) // 队头元素{if(h == t) cout << "ERR_CANNOT_QUERY" << endl;else cout << q[h] << endl;}else // 元素个数{cout << t - h << endl;}}return 0;
}
4.2. P1540 [NOIP 2010 提高组] 机器翻译
P1540 [NOIP 2010 提高组] 机器翻译 - 洛谷
思路: 用队列来实现先进先出的特性, 即模拟内存.
#include <iostream>
#include <queue>using namespace std;const int N = 1010;int m, n;
queue<int> q; // 充当内存
bool st[N]; // st[i] 表示 i 这个元素是否在队列里面int main()
{cin >> m >> n;int cnt = 0;for(int i = 1; i <= n; i++){int x; cin >> x;if(st[x]) continue;cnt++;q.push(x);st[x] = true;if(q.size() > m){st[q.front()] = false;q.pop();}}cout << cnt << endl;return 0;
}
4.3. P2058 [NOIP 2016 普及组] 海港
P2058 [NOIP 2016 普及组] 海港 - 洛谷
题意理解:这个题目意思是以某船的到达时间为截至时间的24h内所有船只的人员国籍数量 注: 请详细阅读题目 -> 题意比较难理解~
思路: 以人{时间, 国家}
为基本单位, 用队列模拟实现先进先出特性来让以某个船的视角来让队列合法化, 最后进行统计即可.
#include <iostream>
#include <queue>using namespace std;typedef pair<int, int> PII;
const int N = 1e5 + 10;int n;
queue<PII> q; // 统计的是 <时间,国家>
int cnt[N]; // cnt[i] 表示 i 国家一共有多少人
int kinds; // 统计国家的种类int main()
{cin >> n;while(n--){int t, k; cin >> t >> k;for(int i = 1; i <= k; i++){int x; cin >> x;// <t, x>q.push({t, x});if(cnt[x]++ == 0) kinds++;}// 让队列合法while(q.size() && q.back().first - q.front().first >= 86400){PII tmp = q.front(); q.pop();int x = tmp.second;if(cnt[x]-- == 1) kinds--;}cout << kinds << endl;}return 0;
}
5. 拓: 双端队列
双端队列: 支持两端的插入删除的线性表.
STL实现: deque
#include <iostream>
#include <deque>using namespace std;struct node
{int x, y, z;
};int main()
{deque<node> q;// 头插for(int i = 1; i <= 5; i++){q.push_front({i, i * 2, i * 3});}// 头删while(q.size()){auto t = q.front(); q.pop_front();cout << t.x << " " << t.y << " " << t.z << endl;}// 尾插for(int i = 1; i <= 5; i++){q.push_back({i, i * 2, i * 3});}// 尾删while(q.size()){auto t = q.back(); q.pop_back();cout << t.x << " " << t.y << " " << t.z << endl;}return 0;
}