当前位置: 首页 > news >正文

算法竞赛中的队列

队列

  • 一.队列
    • 1.基本概念
      • 1.1 核心特性:
    • 2.模拟实现
    • 二.习题:【模板】队列
    • 1.题目
    • 2.解题思路
      • 2.1 数据结构选择
      • 2.2 操作实现
      • 2.3 流程控制
    • 3.参考代码
    • 三.习题:机器翻译
    • 1.题目
    • 2.解题思路
      • 2.1 解题关键字
      • 2.2解题思路
    • 3.参考代码
    • 四.习题:海港
    • 1.题目
    • 2.解题思路
      • 2.1 题眼
      • 2.2 解题思路
    • 3.参考代码

Hello,小伙伴们!又到了咱们一起捣鼓代码的时间啦!💪 把生活调成热情模式,带着满满的能量钻进编程的奇妙世界吧——今天也要写出超酷的代码,冲鸭!🚀
在这里插入图片描述
我的博客主页:喜欢吃燃面
我的专栏:《C语言》,《C语言之数据结构》,《C++》,《Linux学习笔记》
感谢你点开这篇博客呀!真心希望这些内容能给你带来实实在在的帮助~ 如果你有任何想法或疑问,非常欢迎一起交流探讨,咱们互相学习、共同进步,在编程路上结伴成长呀!

一.队列

1.基本概念

在C++中,队列(Queue) 是一种遵循 “先进先出(FIFO,First-In-First-Out)” 原则的线性数据结构,即第一个进入队列的元素会第一个被取出,类似现实中的排队场景。

1.1 核心特性:

  1. 操作受限:仅允许在 队尾(rear) 插入元素(入队),在 队头(front) 移除元素(出队),不支持随机访问中间元素。

  2. 常用操作

    • push(x):在队尾插入元素 x
    • pop():移除队头元素(无返回值)。
    • front():返回队头元素(不删除)。
    • back():返回队尾元素(不删除)。
    • empty():判断队列是否为空(空返回 true)。
    • size():返回队列中元素的个数。
  3. 实现方式

    • C++标准库中提供 std::queue(定义在 <queue> 头文件中),底层通常基于双向队列(deque)或链表实现,无需手动管理内存。
    • 也可手动用数组或链表实现简单队列(如固定大小的循环队列)。
  4. 适用场景

    • 处理按顺序执行的任务(如任务调度、广度优先搜索BFS)。
    • 缓冲场景(如打印机任务队列、消息队列)。

如果想更具体了解队列的相关内容:数据结构之队列

2.模拟实现

#include<iostream>
using namespace std;// 定义队列最大容量(1000)
const int N = 1e3;
// 队列存储数组,h为队头指针,t为队尾指针(初始均为0)
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]; }// 获取队列大小:队尾与队头指针的差值即为元素个数
int size() { return t - h; }// 判断队列是否为空:队头与队尾指针相等时为空
bool empty() { return h == t; }int main() {// 测试入队、出队、判空、大小、队头队尾push(1);push(2);push(3);cout << "队列大小: " << size() << endl;cout << "队头元素: " << front() << endl;cout << "队尾元素: " << back() << endl;pop();cout << "出队后队头元素: " << front() << endl;cout << "队列是否为空: " << (empty() ? "是" : "否") << endl;pop();pop();cout << "队列是否为空: " << (empty() ? "是" : "否") << endl;return 0;
}

二.习题:【模板】队列

1.题目

【模板】队列
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.解题思路

要解决这个队列实现问题,我们可以采用数组模拟队列的思路,通过两个指针 h(队头)和 t(队尾)来维护队列的状态。

2.1 数据结构选择

使用数组 q 存储队列元素,h 记录队头的前一个位置(初始为0),t 记录队尾位置(初始为0)。当 h == t 时,队列为空。

2.2 操作实现

  • push(x)(入队):将元素 x 存入队尾,即 q[++t] = x,队尾指针 t 后移。
  • pop()(出队):若队列为空(h == t),输出 ERR_CANNOT_POP;否则队头指针 h 后移(逻辑上删除队头元素)。
  • query()(查询队头):若队列为空(h == t),输出 ERR_CANNOT_QUERY;否则输出 q[h+1](队头元素在 h+1 位置)。
  • size()(查询队列长度):队列长度为 t - h

2.3 流程控制

读取操作次数 n,然后循环 n 次处理每个操作:根据输入的操作类型(1、2、3、4),分别执行入队、出队、查询队头、查询长度的逻辑。

这种数组模拟的方式简单高效,能在 O(1)O(1)O(1) 时间复杂度内完成所有队列操作,适用于本题的需求。

3.参考代码

#include<iostream>
using namespace std;const int N = 1e4 + 10;  // 定义队列最大容量
int q[N];  // 用数组存储队列元素
int h, t;  // h为队头索引,t为队尾索引(初始均为0)int main()
{int n;cin >> n;  // 输入操作次数while (n--)  // 循环处理n次操作{int op;cin >> op;  // 输入操作类型if (op == 1) {  // 操作1:入队int x;cin >> x;q[++t] = x;  // 队尾指针后移并存入元素}else if (op == 2) {  // 操作2:出队if (t == h)  // 队空时无法出队cout << "ERR_CANNOT_POP" << endl;else++h;  // 队头指针后移(逻辑删除)}else if (op == 3) {  // 操作3:查询队头元素if (t == h)  // 队空时无法查询cout << "ERR_CANNOT_QUERY" << endl;elsecout << q[h + 1] << endl;  // 输出队头元素}else  // 操作4:查询队列长度cout << t - h << endl;  // 长度为队尾与队头的差值}return 0;
}

三.习题:机器翻译

1.题目

机器翻译
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.解题思路

2.1 解题关键字

  • 内存容量(M)
  • 文章长度(N)
  • 英文单词(非负整数表示)
  • 内存查找
  • 外存词典查找(计数目标)
  • 先进先出(FIFO)缓存淘汰
  • 队列(模拟内存缓存)

2.2解题思路

这道题本质是模拟缓存的FIFO(先进先出)淘汰机制,用队列来模拟内存缓存,统计需要从外存词典查找的次数(即新单词入队的次数)。

  1. 数据结构选择
    用数组 q[M] 结合队头指针 h、队尾指针 t 实现队列,模拟内存缓存。队列的长度 t - h 表示当前内存中存储的单词数。

  2. 核心逻辑

    • 对于每个输入的单词 x,先检查是否在当前内存(队列)中(通过 find 函数遍历队列)。
    • 不在内存中
      • 若内存未满(t - h < M),直接将 x 入队,外存查找次数 cnt 加1。
      • 若内存已满(t - h == M),先将队头元素出队(淘汰最早进入的单词),再将 x 入队,外存查找次数 cnt 加1。
    • 在内存中,无需操作,继续处理下一个单词。
  3. 初始化与边界处理
    初始时队列空(h = t = 0),确保每次处理单词时队列状态正确。通过 empty 函数判断队列是否为空(虽然本题逻辑中可由 t - h 替代,但保持函数封装性更清晰)。

这种思路通过队列精准模拟了题目中“内存满则淘汰最早进入的单词”的规则,最终 cnt 即为需要外存查找词典的次数。

3.参考代码

#include<iostream>
using namespace std;const int M = 110;int q[M], t, h;  // t:队尾指针, h:队头指针(初始均为0,队列为空时即h==t)// 出队:队头指针后移
void pop() { ++h; }// 入队:队尾指针后移并赋值
void push(const int& x) { q[++t] = x; }// 查找元素是否在队列中
bool find(const int& x) {// 从队头下一个元素遍历到队尾for (int i = h + 1; i <= t; ++i) {if (q[i] == x) return true;}return false;
}// 判断队列是否为空
bool empty() { return h == t; }int main() {int m, n, cnt = 0;cin >> m >> n;while (n--) {int x;cin >> x;bool exists = find(x);  // 提前判断元素是否存在,减少重复计算if (!exists) {  // 元素不存在时才需要处理入队if (t - h < m) {  // 队列未满push(x);} else {  // 队列已满,先出队再入队pop();push(x);}cnt++;  // 只有新元素入队时计数}// 元素已存在则不做操作(隐含continue)}cout << cnt << endl;return 0;
}

四.习题:海港

1.题目

海港

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.解题思路

2.1 题眼

  1. 时间窗口统计:核心是维护“最近86400秒(24小时)”的时间窗口,统计该窗口内出现的不同元素(如国籍、ID等)的种类数。
  2. 队列+计数数组:用队列存储元素的“出现时间”和“值”,保证元素按时间顺序排列;用计数数组记录每个元素在当前窗口内的出现次数,辅助统计种类数。
  3. 动态清理过期元素:每次新增元素后,需循环移除窗口外的旧元素(时间差≥86400秒),并同步更新计数和种类数,确保统计结果实时准确。

2.2 解题思路

  1. 数据结构选择

    • 队列(queue<pair<int,int>>):按时间顺序存储元素的“出现时间”和“值”,便于快速获取最早出现的元素(队首),判断是否过期。
    • 计数数组(cnt[N]):记录每个元素在当前窗口内的出现次数,避免重复统计种类。
    • 种类计数器(kinds):实时记录窗口内不同元素的总种类数,简化输出。
  2. 核心流程

    • 输入处理:每次读取一批元素(如某时间到达的多个乘客),将其“时间+值”存入队列,并更新计数数组(若元素首次出现,kinds加1)。
    • 清理过期元素:以当前时间为基准,循环检查队首元素是否超出24小时窗口(当前时间 - 队首时间 ≥ 86400)。若过期,弹出队首并减少对应元素的计数,若计数减为0,kinds减1(该元素已完全离开窗口)。
    • 输出结果:每次处理完一批元素后,输出当前窗口内的种类数kinds
  3. 关键逻辑

    • 队列保证元素按时间有序,只需从队首开始清理过期元素(无需检查中间元素)。
    • 计数数组避免因元素重复出现而误减种类数(仅当元素计数从1减为0时,才减少kinds)。

3.参考代码

#include<iostream>
#include<queue>
using namespace std;typedef pair<int,int> PII;  // 定义pair类型,存储(到达时间,国籍)
const int N=1e5+10;         // 定义数组大小常量
int cnt[N];                 // 统计每个国籍的出现次数
int kinds;                  // 统计不同国籍的种类数
queue<PII> q;               // 队列,存储所有在时间窗口内的(时间,国籍)对int main()
{int n;cin>>n;           // 输入船只数量nwhile(n--)              // 处理每一艘船的信息{int t,k;cin>>t>>k;  // 输入当前船的到达时间t和乘客数量kfor(int i=0;i<k;i++){int x;cin>>x;   // 输入每个乘客的国籍xq.push({t,x});  // 将(到达时间,国籍)加入队列if(cnt[x]++==0) // 若该国籍是首次出现,种类数kinds加1kinds++;}// 循环清理超出24小时(86400秒)时间窗口的国籍记录while(!q.empty() && t-q.front().first>=86400){PII tmp=q.front();q.pop();  // 取出并弹出队首元素int x=tmp.second;           // 获取该元素的国籍if(cnt[x]--==1)             // 若该国籍计数减为0,种类数kinds减1kinds--;}cout<<kinds<<endl;  // 输出当前时间窗口内的不同国籍种类数}return 0;
}
http://www.dtcms.com/a/607687.html

相关文章:

  • 郑州网站竞价托管上传图片分享链接
  • 网站建设属于什么职位六盘水网站开发
  • 在线做爰直播网站广州注册公司一网通
  • HashSet和LinedHashSet
  • MyBatis学习
  • 在国外做h网站怎么样越南的网站建设
  • 目录做排名 网站万网搜官网
  • asp网站制作工具网站建设能给客户带来什么
  • 绵阳微网站制作做系统的图标下载网站
  • 网站建设免费网站初中学历怎么提升大专学历
  • 五度易链大数据治理实战:从数据孤岛到智能决策
  • Java入门学习第三章
  • 好的网站具备wordpress移动端设置
  • 个人电脑建立网站会上海包装设计公司排名
  • 免费凡科网站国家建设执业注册中心网站
  • 电商网站建设如何河北通信网站建设
  • 诚信网站备案临沂市经济开发区建设局网站
  • TypeScript类型守卫与可辨识联合详解一
  • 闲鱼钓鱼网站怎么做天津网站开发工资水平
  • 1.3 SubShader
  • 中信建设有限责任公司内部网站做胃镜需那好天津津门网站A
  • 从裸机到RTOS:基于MCU硬件特性的架构演进与范式转移
  • 建设厅网站174号文打电话来说做网站_然后答应了
  • [科普] GNSS授时原理
  • 厦门做商城网站拖拽式建站wordpress
  • 杭州免费网站制作创建网站的流程是什么
  • 淄博做网站手游官网首页
  • wordpress多本小说站出售admin管理员登录
  • Ansible之Playbook简单应用
  • 美橙互联网站建设下载百度2023最新版