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

【数据结构】队列(Queue)详解——数据结构的“先进先出”

在学习数据结构的过程中,**队列(Queue)是继栈之后非常重要的一个结构。队列遵循先进先出(FIFO)**的原则,常常用于任务调度、消息处理等场景。今天我们将一起深入了解队列的基本概念、常见类型(普通队列、循环队列、链式队列)以及它们的实现方法。


一、什么是队列?

队列(Queue)是一种线性数据结构,它的特点是先进先出(FIFO)
队列的元素总是从队头(front)移除,而从队尾(rear)插入。你可以把队列想象成排队买票,最先排队的人最先买到票。

🧩 队列的形象比喻

假设你和朋友们排队买冰淇淋。你站在队伍的队尾,大家按照顺序排队,队伍中的每个人依次向前,直到最先排队的人先买到冰淇淋。你是队列中的一个元素,等待自己的回合。

  • 队头(front):最先排队的人。
  • 队尾(rear):最后排队的人。

队列操作简介

  • 入队(Enqueue):向队列的队尾插入元素。
  • 出队(Dequeue):从队列的队头移除元素。
  • 队头元素(Front):获取队头元素,但不移除。
  • 队列是否为空(isEmpty):检查队列是否为空。
  • 队列是否满(isFull):检查队列是否已满(仅对固定大小的队列有用)。

二、普通队列

📦 普通队列的定义

普通队列是最基础的队列类型。它使用一个数组来存储队列的元素,通过两个指针(frontrear)来表示队头和队尾的位置。

🌿 普通队列的实现(C++)

#include <iostream>
using namespace std;#define MAX_SIZE 5  // 队列最大容量class Queue {
private:int arr[MAX_SIZE];  // 队列存储元素的数组int front;          // 队头指针int rear;           // 队尾指针public:Queue() {front = -1;  // 初始化队头为-1,表示队列为空rear = -1;   // 初始化队尾为-1}// 入队操作void enqueue(int value) {if (rear == MAX_SIZE - 1) {cout << "队列已满,无法入队!" << endl;return;}if (front == -1) front = 0;  // 如果队列为空,设置队头为0arr[++rear] = value;  // 队尾指针向后移动,插入元素cout << "入队:" << value << endl;}// 出队操作void dequeue() {if (front == -1 || front > rear) {cout << "队列为空,无法出队!" << endl;return;}cout << "出队:" << arr[front++] << endl;  // 队头指针向后移动,移除元素}// 获取队头元素int frontElement() {if (front == -1 || front > rear) {cout << "队列为空!" << endl;return -1;}return arr[front];  // 返回队头元素}// 检查队列是否为空bool isEmpty() {return front == -1 || front > rear;}// 打印队列内容void print() {if (front == -1 || front > rear) {cout << "队列为空!" << endl;return;}cout << "队列内容:";for (int i = front; i <= rear; i++) {cout << arr[i] << " ";}cout << endl;}
};

💻 使用普通队列的演示(C++ 示例)

int main() {Queue q;q.enqueue(10);q.enqueue(20);q.enqueue(30);q.enqueue(40);q.enqueue(50);q.print();  // 输出队列内容q.dequeue();  // 出队q.dequeue();  // 出队q.print();  // 输出队列内容cout << "队头元素:" << q.frontElement() << endl;return 0;
}

🧑‍💻 代码输出:

入队:10
入队:20
入队:30
入队:40
入队:50
队列内容:10 20 30 40 50
出队:10
出队:20
队列内容:30 40 50
队头元素:30

三、循环队列

📦 循环队列的定义

循环队列是对普通队列的一种改进。普通队列存在一个问题,当队列的元素被移除后,虽然队列的空间被释放了,但是队头指针和队尾指针可能会一直保持在队列的开头部分,这就导致了空间浪费

为了避免这个问题,循环队列通过将队尾指针和队头指针做循环利用,实现队列的循环存储。换句话说,当队尾指针到达数组的末尾时,它会重新回到数组的开头。

🌿 循环队列的实现(C++)

#include <iostream>
using namespace std;#define MAX_SIZE 5  // 队列最大容量class CircularQueue {
private:int arr[MAX_SIZE];  // 队列存储元素的数组int front;          // 队头指针int rear;           // 队尾指针public:CircularQueue() {front = rear = -1;  // 初始化队列为空}// 入队操作void enqueue(int value) {if ((rear + 1) % MAX_SIZE == front) {  // 队列已满cout << "队列已满,无法入队!" << endl;return;}if (front == -1) front = 0;  // 如果队列为空,设置队头为0rear = (rear + 1) % MAX_SIZE;  // 循环队尾指针arr[rear] = value;  // 插入元素cout << "入队:" << value << endl;}// 出队操作void dequeue() {if (front == -1) {cout << "队列为空,无法出队!" << endl;return;}cout << "出队:" << arr[front] << endl;if (front == rear) {  // 队列只有一个元素front = rear = -1;} else {front = (front + 1) % MAX_SIZE;  // 循环队头指针}}// 获取队头元素int frontElement() {if (front == -1) {cout << "队列为空!" << endl;return -1;}return arr[front];  // 返回队头元素}// 检查队列是否为空bool isEmpty() {return front == -1;}// 打印队列内容void print() {if (front == -1) {cout << "队列为空!" << endl;return;}cout << "队列内容:";int i = front;while (i != rear) {cout << arr[i] << " ";i = (i + 1) % MAX_SIZE;  // 循环遍历}cout << arr[rear] << endl;  // 打印队尾元素}
};

💻 使用循环队列的演示(C++ 示例)

int main() {CircularQueue q;q.enqueue(10);q.enqueue(20);q.enqueue(30);q.enqueue(40);q.enqueue(50);q.print();  // 输出队列内容q.dequeue();  // 出队q.dequeue();  // 出队q.print();  // 输出队列内容cout << "队

头元素:" << q.frontElement() << endl;

return 0;

}


### 🧑‍💻 代码输出:

入队:10
入队:20
入队:30
入队:40
入队:50
队列内容:10 20 30 40 50
出队:10
出队:20
队列内容:30 40 50
队头元素:30


---## 四、链式队列### 📦 链式队列的定义**链式队列**使用**链表**来实现队列。在链式队列中,每个元素(节点)不仅包含数据,还包含指向下一个元素的指针。链式队列的优点是可以动态地扩展,不会受到固定容量的限制。### 🌿 链式队列的实现(C++)```cpp
#include <iostream>
using namespace std;struct Node {int data;Node* next;
};class LinkedQueue {
private:Node* front;  // 队头指针Node* rear;   // 队尾指针public:LinkedQueue() {front = rear = nullptr;  // 初始化队列为空}// 入队操作void enqueue(int value) {Node* newNode = new Node();newNode->data = value;newNode->next = nullptr;if (rear == nullptr) {front = rear = newNode;  // 如果队列为空,头尾指针都指向新节点} else {rear->next = newNode;  // 将新节点加入队尾rear = newNode;}cout << "入队:" << value << endl;}// 出队操作void dequeue() {if (front == nullptr) {cout << "队列为空,无法出队!" << endl;return;}Node* temp = front;cout << "出队:" << temp->data << endl;front = front->next;  // 队头指针后移delete temp;  // 释放内存}// 获取队头元素int frontElement() {if (front == nullptr) {cout << "队列为空!" << endl;return -1;}return front->data;  // 返回队头元素}// 检查队列是否为空bool isEmpty() {return front == nullptr;}// 打印队列内容void print() {if (front == nullptr) {cout << "队列为空!" << endl;return;}cout << "队列内容:";Node* temp = front;while (temp != nullptr) {cout << temp->data << " ";temp = temp->next;}cout << endl;}
};

五、小结

队列类型特点优点缺点
普通队列使用数组实现,队头和队尾使用指针管理实现简单,适用于固定大小的队列队列满时无法扩展,空间利用率低
循环队列对普通队列的优化,通过循环利用数组空间更高效的空间利用需要处理队头和队尾指针的循环问题
链式队列使用链表实现,队列元素动态分配空间动态扩展,适合不确定大小的队列节点管理复杂,增加了内存开销

http://www.dtcms.com/a/541581.html

相关文章:

  • 【操作系统】计算机系统概述
  • 为什么Android游戏画面在30帧运行时有抖动现象
  • 做的好的手机网站建设银行官方网站认证
  • 云南建设厅网站备案厂家域名审核怎么做返利网站
  • docker compose配置容器只允许指定的外部IP访问
  • 【postgresql在sql的基础上将frvcd按照逗号分割,核查两个表中frvcd数量是否相同】
  • 考研政治(马原)
  • 电商网站开发工作室商务网站模板
  • 金融交易防护:国密 SSL 证书在网银与移动支付中的核心作用
  • 织梦图片瀑布流网站模板摄影作品发布平台
  • spark-RDD期中
  • Linux 网络初识
  • 易天光通信光模块认证全解析:构建全球品质信任网络
  • 计算机网络自顶向下方法12——应用层 对HTTP响应报文优先次序的答疑
  • 上海企业建设网站服务网站的首页标题在哪里设置的
  • 城市建设规划网站无锡网站建设f7wl
  • 算法题 逆波兰表达式/计算器
  • 智能体最佳实践的方法论(四):监控
  • 【java面向对象进阶】------内部类
  • 基于昇腾 NPU 的 Gemma 2 推理实测:性能评测、脚本实现与可视化分析
  • 南京设计公司郑州粒米seo顾问
  • 承接电商网站建设中文网站模板大全
  • 折半查找及其判定树的性质
  • Day 6 PPI与Cox
  • 网站dns刷新庐江县建设局网站
  • 网站的按钮怎么做 视频3g 手机网站建设
  • 豆包凶猛,深度解析字节AI战略
  • 【案例实战】HarmonyOS云开发实战:5分钟快速构建全栈应用
  • 为什么你的React项目到中等规模就开始“烂尾“?问题可能出在文件结构
  • 做思维导图好看的网站企业网络规划开题报告