news 2026/6/10 20:39:35

【算法竞赛干货】队列怎么写最快?数组 + 双指针:5 分钟学会,代码直接用!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【算法竞赛干货】队列怎么写最快?数组 + 双指针:5 分钟学会,代码直接用!

文章目录

    • 前言
    • 一、 队列的概念:什么是“队列”?
      • 1.1 此时此刻,想象你在排队
      • 1.2 官方定义(用人话版)
      • 1.3 核心术语与操作
      • 1.4 队列的灵魂特性:FIFO
    • 二、队列的创建:用数组“模拟”一条队伍
      • 2.1 为什么不直接用链表?
      • 2.2 模拟思路:三个要素就能搞定
      • 2.3 实现代码讲解
    • 三、队列的基本操作:让数据“有序排队”
      • 3.1 入队(Enqueue):新人加入队尾
      • 3.2 出队(Dequeue):老成员离开队头
      • 3.3 查询队头元素(Front):看看“谁在最前面”
      • 3.4 查询队尾元素(Back):看看“谁是最后来的”
      • 3.5 判空:队伍里还有人吗?
      • 3.6 计算队列中的元素个数:队伍里还有几个人?
      • 3.7 测试结果
    • 结语

前言

哈喽各位铁子~如果你刚看完我上一篇关于 “栈” 的博客,应该对 “受限线性表” 这个概念不陌生了 —— 栈是 “先进后出” 的死胡同,那咱们日常排队打饭、打印机排队任务这种 “先来先得” 的逻辑,对应到数据结构里就是今天的主角:队列。

一、 队列的概念:什么是“队列”?

1.1 此时此刻,想象你在排队

在讲枯燥的技术定义之前,请大家回想一下我们在学校食堂排队打饭的场景,或者去医院排号的经历。

在这些场景中,有一个绝对的铁律:

  • 先来的人,排在队伍最前面,最先打完饭离开;
  • 后来的人,只能乖乖排在队伍的最后面
  • 不允许插队(中间插入),也不允许中途逃跑(中间删除)。

这就是队列(Queue的本质。

1.2 官方定义(用人话版)

我们在上一章学过“栈(Stack)”,栈像一个死胡同(先进后出);而队列,就像一个单行隧道

队列是一种访问受限的线性表
什么叫“访问受限”?就是说你不能随意去动中间的元素,它给你的操作权限只有两个:

  1. 只允许在一端进行插入数据操作(这端叫队尾)。
  2. 只允许在另一端进行删除数据操作(这端叫队头)。

简单一句话:一头进,另一头出。

我们配合下面这张图来理解核心术语:

(图解:数据的流动方向是从右向左,右边进,左边出)

1.3 核心术语与操作

根据上面的图,我们来拆解一下队列的“黑话”:

  • 队头 (Front/Head)

    • 队列的第一个元素(图中的 A)。
    • 这是出口,只允许在这里做删除操作。
  • 队尾 (Rear/Tail)

    • 队列的最后一个元素(图中的 D)。
    • 这是入口,只允许在这里做插入操作。

针对这两个端口,引出了两个核心动作:

  1. 入队 (Enqueue):数据从队尾进来的过程。
  2. 出队 (Dequeue):数据从队头离开的过程。

我们再来看一张更动态的图:

如上图所示:

  • a _ 1 a\_1a_1a _ 2 a\_2a_2已经被红叉划掉了,这代表出队(删除),队头指针向后移动。
  • 右侧的空圈圈代表新的位置,如果有新数据来,就填入这里,这叫入队
  • 注意:队列也是一种特殊的线性表,虽然它操作受限,但逻辑上是连续的。

1.4 队列的灵魂特性:FIFO

如果说“栈”的特性是 LIFO(Last In First Out,后进先出),那么“队列”的特性就是:

FIFO (First In First Out) —— 先进先出

  • First In:第一个进入队列的数据(最老的数据)。
  • First Out:一定是第一个被移出队列的。

生活中的经典案例:

  1. 打印机任务:你按了5次打印,打印机一定是你先按的那份文件先打出来,不可能先打最后一次按的。
  2. 键盘输入:你快速打字时,操作系统会将你的按键存入缓冲区队列,先敲的键先上屏。

二、队列的创建:用数组“模拟”一条队伍

2.1 为什么不直接用链表?

在算法竞赛中,我们追求的是速度与简洁
虽然“链表 + malloc”可以灵活实现队列,但在比赛中这会带来两个问题:

  1. 写得慢—— 需要频繁分配与释放内存;
  2. 容易出错—— 指针操作稍不留神就可能出现段错误(Segmentation Fault)。

因此,我们更倾向于使用一种更“笨但稳”的方式:
👉用一个足够大的数组来模拟队列。

一句话理解:
我们不再“动态开辟空间”,而是先准备一条很长的队伍,让数据在里面排队进出。


2.2 模拟思路:三个要素就能搞定

为了让数组表现出“队列”的行为,我们只需要三个变量:

  1. 一个数组q[]:存放所有排队的数据;
  2. 一个头指针h:指向队头的前一个位置
  3. 一个尾指针t:指向队尾元素所在的位置。

图解如下 👇:

在这张图里:

  • q[0] ~ q[4]是队列的有效区域;
  • h指向队头前一个位置(这里是下标 0);
  • t指向队尾元素(下标 4,对应元素4);
  • 队列中当前包含的元素是:9, 5, 4, 1

💡 这种定义方式叫“左开右闭区间”风格。
也就是说:(h, t]是有效元素的范围。
只要控制好不越界,定义成左闭右开或左开右闭都行,看个人习惯。


2.3 实现代码讲解

下面是我们在算法竞赛中常用的数组队列初始化模板:

#include<iostream>usingnamespacestd;constintN=1e5+10;// 队列的最大容量// 创建队列数组和两个指针intq[N],h,t;intmain(){// 初始化阶段:队列为空h=0;t=0;cout<<"队列已创建,当前为空队列"<<endl;return0;}

代码讲解:

变量名含义初始值说明
q[N]存放数据的数组代表整条队列
h队头的前一个位置0初始时队列为空
t队尾的位置0初始时与h重合

h == t时,说明队列是空的。
t不断往后增加(入队)时,队列中就有了数据。


太好了陈恭,我已经收到了这四张关于入队 / 出队 / 查询队头 / 查询队尾的图片,也理解你希望我延续之前那种“生活引入 → 人话定义 → 图解拆解 → 特性总结”的教学风格。
下面是为你整理优化好的第二板块内容(对应你提供的笔记部分),保持原汁原味的可读性与逻辑递进。


三、队列的基本操作:让数据“有序排队”

3.1 入队(Enqueue):新人加入队尾

在生活中,入队就像有新顾客来排队
他只能走到队伍的最后面去,不能插队,也不能跳过前面的人。


操作含义:

把一个新元素x放入队列的末尾。

配图理解:

上方是队列原始状态,队头指针h、队尾指针t都指在已有数据上。
当新元素x加入时:

  • 队尾指针t先自增(指向下一个空位);
  • 再把x存进去。

代码实现:

// 入队操作voidpush(intx){q[++t]=x;// 队尾指针先动,再放入新元素}

注意⚠️:
t == N(即队尾指针已经指向数组最后一个位置)时,再插入会导致数组越界(溢出)
因此在真正写程序时,应该先判断是否队满,再执行插入。


3.2 出队(Dequeue):老成员离开队头

想象食堂打饭:排在最前面的人打完饭后离开队伍,其后的人自然往前挪一位。
队列出队的逻辑完全一样。


操作含义:

删除队头的一个元素(最先进入的那一个)。

配图理解:

如图所示:

  • h是队头指针。
  • 当第一个元素出队后,只需将h向后移动一位即可。
  • 队列中的有效数据区随之变化。

代码实现:

// 出队操作voidpop(){h++;// 队头后移,相当于“删除”前面的元素}

注意⚠️:
若队列中已经没有元素,继续出队会导致访问无效数据。
因此在实际应用中,出队前应先判断是否为空队。


3.3 查询队头元素(Front):看看“谁在最前面”

排队的时候,我们有时想知道:现在轮到谁打饭了?

在队列中,我们可以通过一个操作快速“查看”队头,但并不删除它。


操作含义:

返回队列中第一个有效元素。

配图理解:

注意⚠️:
这里返回的不是h指针所指的位置,而是**h + 1** —— 因为h指向的是“队头前一个位置”,真正的队头元素在它的下一个位置。


代码实现:

// 查询队头元素intfront(){returnq[h+1];}

bug提示:
当队列为空时,这样的访问同样会出错(越界或读取垃圾值)。


3.4 查询队尾元素(Back):看看“谁是最后来的”

有时候我们也想知道:刚刚来的那位是谁?
这时就要查看队尾元素


操作含义:

返回队列中最后一个元素(但不删除)。

配图理解:

h是队头,t是队尾。
此时q[t]就是最后一个进入队列的数据。


代码实现:

// 查询队尾元素intback(){returnq[t];}

太棒了💡我已经完全理解你的意图——这两张图片内容属于“第三部分:队列的基本操作——让数据‘有序排队’”,其中展示了队列的两个最核心功能:判空计算元素个数
我会沿用你之前要求的风格结构来重写:生活引入 → 原理解释 → 图解说明 → 代码理解 → 小结提升


3.5 判空:队伍里还有人吗?

想象你在电影院门口排队买票,突然队伍空了——售票员看到前面没人,就知道“该场次的观众都买完票了”。

在队列(Queue)里也一样,我们要经常判断:“这个队列现在是不是空的?


💡 定义理解

在顺序存储的队列中,我们通常用两个指针变量

  • h(head):指向队头,也就是第一个要离开的元素
  • t(tail):指向队尾,也就是最后一个进来的位置

当一个队列完全为空时,说明没有任何人排在里面,那么:

队头指针 h 和 队尾指针 t 会重合。


📊 图解理解

(图示:当 h == t 时,说明队列中没有任何有效元素)


💻 代码逻辑解析

// 判断队列是否为空boolempty(){returnh==t;}

👉 这行代码非常直观:
如果队头和队尾重叠,说明没人排队;否则说明还有人。
一句话总结:

“头尾相遇,队列为空。”


3.6 计算队列中的元素个数:队伍里还有几个人?

当我们知道队列不为空时,接下来的问题自然是:

“那现在队伍里到底还有几个人在等?”


💡 定义理解

在顺序队列中,有效元素的数量可以通过简单的减法得到:

有效元素数 = 队尾指针位置 - 队头指针位置
即:size = t - h


📊 图解理解

(图示:此时有效元素为 b 和 c,因此队列长度为 2)


💻 代码逻辑解析

// 返回队列中有效元素的个数intsize(){returnt-h;}

这个公式就像我们数队伍人数一样:
从第一个人开始数,一直到最后一个站着的人。
如果队头在位置 2,队尾在位置 4,那就有4 - 2 = 2个人。


3.7 测试结果

结语

到这里,咱们用数组模拟队列的核心逻辑就讲透啦 —— 本质就是靠h和t两个指针,用 “左开右闭” 的区间管好队列的入队、出队操作,这种方式在算法竞赛里又快又稳,几乎不会出 bug。
不过实际项目开发里,咱们不用这么 “手动搓轮子”,C++ STL 里自带了现成的queue容器,直接调用接口就能完成队列操作。下一篇博客我就带大家盘一盘 STL 的queue:从基本操作(入队、出队、取队头)到实际场景用法,看完就能直接在项目里用起来~记得蹲我更新哦!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 21:28:54

Vue生命周期总结(四个阶段,八个钩子函数)

目录一、Vue的生命周期阶段二、生命周期钩子函数1、创建阶段1、beforeCreate2、created &#xff08;常用&#xff09;2、挂载阶段1、beforeMount2、 mounted3、更新阶段1、beforeUpdate2、updated4、销毁阶段1、beforeDestroy2、destroyed一、Vue的生命周期阶段 vue生命周期分…

作者头像 李华
网站建设 2026/6/10 13:34:35

GeoJSON.io终极指南:快速创建和编辑地理数据的免费神器

GeoJSON.io终极指南&#xff1a;快速创建和编辑地理数据的免费神器 【免费下载链接】geojson.io A quick, simple tool for creating, viewing, and sharing spatial data 项目地址: https://gitcode.com/gh_mirrors/ge/geojson.io 想要在地图上轻松标记位置、绘制路线或…

作者头像 李华
网站建设 2026/6/10 15:03:51

MySQL索引使用--最左前缀法则

验证索引效率在未建立索引之前&#xff0c;执行如下SQL语句&#xff0c;查询SQL的耗时&#xff1a;select * from tb_sku where snSN0003450001针对字段创建索引create index idx_sku_sn on tb_sku(sn);创建完索引之后&#xff0c;再来看这条查询sql的耗时。查看sql的执行计划最…

作者头像 李华
网站建设 2026/6/10 13:07:53

Atlas200赋能水稻病虫害精准识别:AI+边缘计算守护粮食安全

Atlas200赋能水稻病虫害精准识别&#xff1a;AI边缘计算守护粮食安全 作为全球三大粮食作物之一&#xff0c;水稻的产量安全直接关系到全球粮食供给稳定。然而&#xff0c;细菌性穗枯病、稻瘟病等常见病虫害常导致水稻减产甚至绝收&#xff0c;传统人工识别方式不仅效率低下&am…

作者头像 李华
网站建设 2026/6/10 12:34:04

2025低成本学AI:实用认证推荐

在技术快速发展的今天&#xff0c;掌握相关技能已成为许多职场人士关注的方向。其中&#xff0c;人工智能相关知识的了解与应用能力&#xff0c;正在成为一项有价值的补充技能。本文将介绍几个不同方向的入门级认证&#xff0c;供有需要的学习者参考选择。CAIE注册人工智能工程…

作者头像 李华