除了前文提到的栈和vector(C++STL常用数据结构1详解---栈(stack)-CSDN博客)
队列和优先级队列(堆)也是十分常用的数据结构……
本文暂且对于优先级队列按下不提,先说明队列的使用(到时又能水一篇了
一、意义
简介
队列是一种先进先出的数据结构。
如上图,最开始时,队列中有一队头(head)与队尾(tail)
操作时,在head插入元素,在tail弹出元素:
定义/声明
与STL的其它数据结构类似,队列的声明需要头文件和存储数据的类型:
#include<queue> //头文件
queue<int> q; //定义名为q,存储int数据的队列
其它也没什么好写的了……吧?
函数集
queue<int> q; //主角
q.push(114); //push(元素):向队头加入元素
int t = q.front(); //front():访问队头元素
q.pop(); //pop():弹出队尾元素
if(q.empty()){...} //empty():返回队列是否为空
int s = q.size(); //size():返回队列中元素个数
拓展:双端队列
顾名思义,双端队列是一种支持在队尾、队头进行插入/查询/弹出操作的队列:
deque<int> dq; //双端队列
//(其它函数和queue基本一样)
dq.push_front(114); //在队头插入元素
dq.push_back(514); //在队尾插入元素
int a = dq.front(); //访问队头
int b = dq.back(); //访问队尾
dq.pop_front(); //弹出队头元素
dq.pop_back(); //弹出队尾元素
应用
(1)约瑟夫问题
洛谷P1996:约瑟夫问题 - 洛谷
简述:n人排成一圈,从第一人开始数,数到m的倍数时此人就出圈,求出圈顺序
思路:没有必要直接模拟,可以看作是一个队列
数到这个人时就将其弹出,如果是m的倍数就输出,否则再重新加入队尾
这样就不会把已经出圈的人再数一遍了
代码如下:
#include<iostream>
#include<queue>
using namespace std;
queue<int> q;
int n, m;
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i++) q.push(i);
int t = 0;
while(!q.empty()){
int a = q.front();
q.pop();
t++;
if(t % m == 0){
cout << a << ' ';
continue;
}else q.push(a);
}
cout << endl;
return 0;
}
(2)广度优先搜索(BFS)
洛B3625:迷宫寻路 - 洛谷
题目简述:' . '为空地,' # '为墙,给定n * m的矩阵
问能否从(1, 1)走到(n, m)
思路:广搜,从(1, 1)开始,每次把相邻的、合法的点加入队列
再对于每一个点向外搜索,看看能不能搜到(n, m)
代码如下:
#include<iostream>
#include<queue>
using namespace std;
#define For(i, j, k) for(int i = j; i <= k; i++)
#define dFor(i, j, k)for(int i = j; i >= k; i--)
//for循环的缩写,方便使用
#define MaxN 105
int n, m, flag;
char a[MaxN][MaxN];
int dx[] = {0, 0, -1, 1};
int dy[] = {1, -1, 0, 0};
//这两个数组手动记录上下左右的x、y偏移量,方便确定坐标
int vis[MaxN][MaxN];
int check(int x, int y){ //检查是否合法(不是墙不越界且没访问过)
return !(x<1||x>n||y<1||y>m) && a[x][y] != '#' && !vis[x][y];
}
void bfs(){
queue<int> qx, qy; //搜索队列
qx.push(1); qy.push(1); //先搜索(1,1)
vis[1][1] = 1; //vis储存是否找过这个点
while(!qx.empty()){
int x = qx.front();
int y = qy.front();
qx.pop(); qy.pop();
//取出队列最上方元素
For(i, 0, 3){ //四个方向
int tx = x + dx[i];
int ty = y + dy[i];
if(tx == n && ty == m){
flag = 1; return ;
//已经搜索到了,直接返回
}
if(check(tx, ty)){
qx.push(tx);
qy.push(ty);
//合法:将其加入搜索队列
vis[tx][ty] = 1;
}
}
}
}
int main()
{
cin >> n >> m;
For(i, 1, n){
For(j, 1, m){
cin >> a[i][j];
}
}
bfs();
if(flag) cout << "Yes\n";
else cout << "No\n";
return 0;
}
结语
总之,队列这个数据结构还是挺有用的啦~
另外感谢大家的点赞和支持,这个系列未来也会继续更新哒
最后不要忘了点个收藏点个赞,关注博主获得最新的更新动态~