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

【数据结构与算法学习笔记】队列

前言

本文为个人学习的算法学习笔记,学习笔记,学习笔记不是经验分享与教学,不是经验分享与教学,不是经验分享与教学,若有错误各位大佬轻喷(T^T)。主要使用编程语言为Python3,各类资料题目源于网络,主要自学途径为博学谷,侵权即删。

一、队列的基本定义与核心特性

1. 定义

队列是一种线性数据结构,严格遵循 “元素从队列尾(Tail)入队、从队列头(Head)出队” 的操作规则,整体满足 “先进先出(First In First Out,FIFO)” 逻辑,类似现实中的 “排队场景”—— 先排队的人先完成操作,后排队的人依次等待。、

2. 核心特性

  • 操作限制:仅允许在队尾执行 “入队(添加元素)”,仅允许在队头执行 “出队(删除元素)”,不支持在队列中间插入 / 删除 / 访问元素。
  • FIFO 原则:先入队的元素必然先出队。例如:元素按「3→2→5→7」的顺序入队后,队列结构为Head → [3, 2, 5, 7] → Tail,出队顺序只能是「3→2→5→7」。

二、队列的 Python 实现(两种核心方式)

根据课件内容,队列可通过数组(列表) 或链表实现,两种方式各有适配场景,以下为完整 Python 代码示例及解析。

1. 数组(列表)实现(含循环队列优化)

课件提到,普通数组实现队列会存在 “假溢出” 问题(队尾到达数组末尾时,即使队头有空闲空间也无法入队),因此需通过循环队列优化,将数组视为 “环形结构”。

实现思路
  • 用列表self.items存储元素,用self.head(队头索引)、self.tail(队尾索引)标记两端,用self.size记录队列最大容量。
  • 入队:判断队列是否未满,将元素存入self.tail位置,self.tail按环形逻辑更新((self.tail + 1) % self.size)。
  • 出队:判断队列是否非空,取出self.head位置的元素,self.head按环形逻辑更新。
Python 代码
class CircularQueue:def __init__(self, capacity):"""初始化循环队列,capacity为队列最大容量"""self.capacity = capacity  # 队列最大容量(对应数组长度)self.items = [None] * capacity  # 存储元素的列表(数组)self.head = 0  # 队头索引,初始为0self.tail = 0  # 队尾索引,初始为0(指向待入队位置)def is_empty(self):"""判断队列是否为空:head == tail且队头元素为None"""return self.head == self.tail and self.items[self.head] is Nonedef is_full(self):"""判断队列是否已满:head == tail且队头元素非None"""return self.head == self.tail and self.items[self.head] is not Nonedef enqueue(self, value):"""入队:在队尾添加元素,返回是否成功"""if self.is_full():print("队列已满,无法入队")return Falseself.items[self.tail] = value  # 元素存入队尾self.tail = (self.tail + 1) % self.capacity  # 队尾环形更新print(f"元素{value}入队成功")return Truedef dequeue(self):"""出队:从队头删除并返回元素,若为空返回None"""if self.is_empty():print("队列为空,无法出队")return Nonevalue = self.items[self.head]  # 取出队头元素self.items[self.head] = None  # 清空队头位置(避免混淆空/满)self.head = (self.head + 1) % self.capacity  # 队头环形更新print(f"元素{value}出队成功")return valuedef get_size(self):"""获取队列当前元素个数"""if self.is_empty():return 0elif self.is_full():return self.capacityelse:return (self.tail - self.head) % self.capacity# 示例:使用循环队列
if __name__ == "__main__":q = CircularQueue(5)  # 初始化容量为5的循环队列q.enqueue(3)  # 元素3入队成功q.enqueue(2)  # 元素2入队成功q.enqueue(5)  # 元素5入队成功q.enqueue(7)  # 元素7入队成功print("当前队列长度:", q.get_size())  # 输出:4q.dequeue()   # 元素3出队成功q.enqueue(9)  # 元素9入队成功(利用环形空闲空间)print("当前队列长度:", q.get_size())  # 输出:4

2. 链表实现

课件指出,链表实现队列可天然避免 “假溢出”,支持动态扩容(无需预先指定容量),核心是用 “头节点” 标记队头、“尾节点” 标记队尾,减少元素移动操作。

实现思路
  • 定义Node类表示链表节点(含value(元素值)和next(下一个节点指针))。
  • 队列类LinkedListQueueself.head(头节点)、self.tail(尾节点)、self.length(元素个数)记录状态。
  • 入队:创建新节点,若队列为空则头、尾节点均指向新节点;否则尾节点的next指向新节点,更新尾节点为新节点。
  • 出队:若队列非空,记录头节点的元素值,更新头节点为head.next,若出队后为空则尾节点也置为 None。
Python 代码
class Node:"""链表节点类:存储元素值和下一个节点指针"""def __init__(self, value):self.value = value  # 节点存储的元素值self.next = None    # 指向后一个节点的指针class LinkedListQueue:def __init__(self):"""初始化空队列:头、尾节点均为None,长度为0"""self.head = None    # 队头节点(指向第一个元素)self.tail = None    # 队尾节点(指向最后一个元素)self.length = 0     # 队列当前元素个数def is_empty(self):"""判断队列是否为空:长度为0"""return self.length == 0def enqueue(self, value):"""入队:在队尾添加新节点"""new_node = Node(value)  # 创建新节点if self.is_empty():# 空队列时,头、尾节点均指向新节点self.head = new_nodeself.tail = new_nodeelse:# 非空队列时,尾节点的next指向新节点,更新尾节点self.tail.next = new_nodeself.tail = new_nodeself.length += 1print(f"元素{value}入队成功")def dequeue(self):"""出队:从队头删除节点并返回元素值,空队列返回None"""if self.is_empty():print("队列为空,无法出队")return None# 记录队头节点的元素值(待返回)dequeued_value = self.head.value# 更新头节点为下一个节点self.head = self.head.nextself.length -= 1# 若出队后为空,尾节点也置为None(避免尾节点指向无效节点)if self.is_empty():self.tail = Noneprint(f"元素{dequeued_value}出队成功")return dequeued_valuedef get_size(self):"""获取队列当前元素个数"""return self.length# 示例:使用链表队列
if __name__ == "__main__":q = LinkedListQueue()q.enqueue(3)  # 元素3入队成功q.enqueue(2)  # 元素2入队成功q.enqueue(5)  # 元素5入队成功print("当前队列长度:", q.get_size())  # 输出:3q.dequeue()   # 元素3出队成功q.enqueue(7)  # 元素7入队成功print("当前队列长度:", q.get_size())  # 输出:3

3. Python 内置模块collections.deque(推荐)

课件提到队列的入队、出队时间复杂度均为 O (1),而 Python 内置的deque(双端队列)恰好满足这一特性 —— 其append()(队尾入队)和popleft()(队头出队)操作均为 O (1),比普通列表的pop(0)(O (n))更高效,适合实际开发。

示例代码
from collections import deque# 初始化队列(空队列)
q = deque()# 入队(队尾添加元素)
q.append(3)
q.append(2)
q.append(5)
q.append(7)
print("入队后队列:", q)  # 输出:deque([3, 2, 5, 7])# 出队(队头删除元素)
dequeued_value = q.popleft()
print("出队元素:", dequeued_value)  # 输出:3
print("出队后队列:", q)  # 输出:deque([2, 5, 7])# 获取队列长度
print("当前队列长度:", len(q))  # 输出:3# 判断队列是否为空
print("队列是否为空:", len(q) == 0)  # 输出:False

三、典型例题:LeetCode 933. 最近的请求次数(Python 实现)

课件明确将该题作为队列的典型应用场景 —— 处理 “按时间顺序产生的请求,筛选特定时间窗口内的请求”,核心思路是利用队列的 FIFO 特性清理 “过期请求”。

1. 题目描述

实现RecentCounter类,计算最近 3000 毫秒内的请求次数:

  • 方法ping(int t):记录请求时间t(毫秒,非递减),返回时间区间[t-3000, t]内的请求总数。

2. 解题思路(对应课件逻辑)

  1. 用队列存储所有请求时间,每次ping时先 “清理队头”—— 删除所有小于t-3000的过期时间(因t非递减,队头是最早请求,过期则后续元素均过期);
  2. 将当前请求时间t入队;
  3. 队列长度即为 “最近 3000 毫秒内的请求数”,直接返回。、

3. Python 代码实现

from collections import dequeclass RecentCounter:def __init__(self):"""初始化:用deque存储请求时间"""self.requests = deque()def ping(self, t: int) -> int:"""处理请求t,返回最近3000毫秒内的请求数"""# 1. 清理过期请求:删除所有小于t-3000的时间(队头开始)while self.requests and self.requests[0] < t - 3000:self.requests.popleft()# 2. 当前请求时间t入队self.requests.append(t)# 3. 队列长度即为结果return len(self.requests)# 示例:验证课件中的测试场景
if __name__ == "__main__":rc = RecentCounter()print(rc.ping(1))      # 时间窗口[-2999,1],返回1print(rc.ping(100))    # 时间窗口[-2900,100],返回2print(rc.ping(3001))   # 时间窗口[1,3001],返回3(清理后队列:[1,100,3001])print(rc.ping(3002))   # 时间窗口[2,3002],返回3(清理后队列:[100,3001,3002])print(rc.ping(3110))   # 时间窗口[110,3110],返回3(清理后队列:[3001,3002,3110])

四、队列知识点小结(基于课件)

  1. 核心逻辑:队尾入队、队头出队,严格 FIFO;
  2. 实现方式
    • 数组实现:需用循环队列解决 “假溢出”,适合已知容量场景;
    • 链表实现:动态扩容,无溢出问题,适合容量不确定场景;
    • 推荐用collections.deque:兼顾效率与便捷性,O (1) 入队 / 出队。
  3. 时间复杂度:入队、出队均为 O (1),与数据规模无关;
  4. 典型应用:请求时间窗口统计(如 LeetCode 933)、任务调度、广度优先搜索(BFS)等。
http://www.dtcms.com/a/431103.html

相关文章:

  • Service Worker:前端离线化与性能优化的核心技术
  • FFmpeg 深入精讲(五)播放器核心技术
  • 迪拜哪个网站是做网站的网络平台有哪些?
  • 【天池经典打榜赛】赛道四-知识图谱预测赛的代码文档
  • typescript 中 for..of 和 for..in的区别
  • 安卓和网站开发找工作wordpress 改网站域名
  • AI 提效:利用 AI 从前端 快速转型为UI/UX设计师和产品
  • 模板网站建站公司公主岭网站建设
  • DAY 37 早停策略和模型权重的保存-2025.10.1
  • 百联网上购物商城南昌百度推广优化排名
  • DataHub:一个现代化的元数据管理平台
  • 做 58 那样的网站wordpress图片外链
  • 腾讯开源 Hunyuan-MT-7B:33语种全覆盖、30项WMT25冠军的轻量级机器翻译新标杆
  • 郑州网站APP网站推广做多大尺寸
  • node.js 二进制安装
  • 【办公类-116-01】20250929家长会PPT(Python快速批量制作16:9PPT相册,带文件名,照片横版和竖版)
  • 鸿蒙应用Hello World
  • 做网站建设优化的公司排名转化率的网站设计
  • 怎么进入官方网站查询python采集数据wordpress
  • Makefile及其在Linux操作系统上的使用
  • 自监督学习在医疗AI中的技术实现路径分析(下)
  • 【复习】计网每日一题--NAV
  • 如何使用腾讯云建网站中信建设有限责任公司领导
  • 找别人做网站要注意什么软件WordPress导航菜单不显示
  • 智能体版中科院学术GPT免费上线内测!AI与科研的深度碰撞
  • 网站开发内部工单广州官方发布
  • 【Android之路】安卓资源与编译初步
  • 解决 Azure DevOps Agent 的 SPNEGO 凭据错误问题
  • 从CUDA安装到onnxruntime部署调用记录
  • 网站设计的论坛最好用的企业网站cms