数据结构与算法——队列

目录

一、队列的基本概念与核心特性

1.定义

2.核心术语

3.常用操作

二、队列的常见分类

1.普通队列

2.循环队列

3.双端队列

4.优先级队列

三、队列的C语言实现

1.循环顺序队列

2.链式队列

四、队列的核心操作复杂度

五、队列的典型应用


一、队列的基本概念与核心特性

1.定义

**队列:**一种只允许在队尾插入元素,在队头删除元素的线性表。

这一特性决定了队列的**"先进先出(FIFO)"**原则,即最早进入队列的元素,最早被取出。

2.核心术语

  • **队头:**允许删除的一端,指向队列中第一个元素的位置。
  • **队尾:**允许插入的一段,指向队列中最后一个元素的下一个位置。
  • 空队列:当队头和队尾指向同一位置。
  • **满队列:**队尾达到存储结构的最大容量。

3.常用操作

  • **初始化:**创建一个空队列。
  • **判空:**判断队列是否为空。
  • **判满:**判断队列是否已满,仅顺序队列需要。
  • **入队:**在队尾插入一个新元素。
  • **出队:**在队头删除一个元素。
  • **获取队头元素:**返回队头元素的值,但不删除该元素。

二、队列的常见分类

1.普通队列

  • **顺序队列:**基于数组实现,需维护队首和队尾指针/下标;缺点是易出现假溢出。
  • 链式队列:基于链表实现,用头节点指向队首、尾节点指向队尾,支持动态扩容,无假溢出问题。

**假溢出:**数组尾部已满但头部有空余空间

2.循环队列

为解决顺序队列的假溢出问题,将数组逻辑上构造成环形,让 head 和 tail 指针在数组中循环移动。其核心是通过取模运算实现 "环形"。

基于效率的考虑,在入队和出队的时候,head 和 tail 均采用直接自增(++)操作。但如果一直自增的话,head 和 tail 会越界。为了准确表达队空、队满的情况,做以下约束:

  • **判空条件:**head == tail
  • 判满条件:(tail + 1) % tlen == head(预留一个空位置避免与判空条件混淆)

3.双端队列

允许在队首和队尾同时执行入队 / 出队操作的特殊队列,可灵活实现 "栈"(仅用一端操作)或 "普通队列" 的功能,常用于滑动窗口等算法场景。

4.优先级队列

打破 FIFO 原则的特殊队列,元素按优先级排序,优先级最高的元素优先出队,底层通常基于实现,常用于任务调度(如嵌入式系统的中断优先级管理)。

三、队列的C语言实现

1.循环顺序队列

固定容量,适合内存受限的嵌入式场景

cpp 复制代码
typedef int DATATYPE;
typedef struct queue {
    DATATYPE *ptr;
    int tlen;
    int head;
    int tail;
}SeqQueue;

// 创建队列
SeqQueue *CreateSeqQueue(int len);

// 出队操作
DATATYPE QuitSeqQueue(SeqQueue *queue);

// 入队操作
int EnterSeqQueue(SeqQueue *queue, DATATYPE data);

// 判空操作
int IsEmptySeqQueue(SeqQueue *queue);

//判满操作
int IsFullSeqQueue(SeqQueue *queue);

// 销毁队列
int DestroySeqQueue(SeqQueue *queue);

为方便理解,下面展示循环顺序队列的结构图:

2.链式队列

动态扩容,适合数据量不固定的场景

cpp 复制代码
typedef struct person
{
    char name[32];
    char sex;
    int age;
    int score;
} DATATYPE;

typedef struct quenode
{
    DATATYPE data;
    struct quenode *next;
} LinkQueNode;

typedef struct
{
    LinkQueNode *head;
    LinkQueNode *tail;
    int clen;
} LinkQue;

// 创建链队
LinkQue * CreateLinkQue();

// 入队操作
int EnterLinkQue(LinkQue *lq,DATATYPE* newnode);

// 出队操作
int QuitLinkQue(LinkQue*lq);

// 获取队头元素
DATATYPE* GetHeadLinkQue(LinkQue *lq);

// 获取链队长度
int GetSizeLinkQue(LinkQue *lq);

// 判空操作
int IsEmptyLinkQue(LinkQue *lq);

// 销毁链队
int DestroyLinkQue(LinkQue * lq);

为方便理解,下面展示链式队列的结构图:

四、队列的核心操作复杂度

|--------|------------|----------|
| 操作 | 循环顺序队列 | 链式队列 |
| 入队 | O(1) | O(1) |
| 出队 | O(1) | O(1) |
| 判空/判满 | O(1) | O(1) |
| 获取队首 | O(1) | O(1) |
| 空间复杂度 | O(n)(固定) | O(n)(动态) |

五、队列的典型应用

  1. 中断数据缓冲:嵌入式系统中,串口 / ADC 等外设的中断接收数据可存入队列,主程序从队列中读取处理,避免数据丢失(如 STM32 的 USART 接收缓冲)。
  2. 任务调度:RTOS(如 FreeRTOS)中,就绪任务队列按优先级或 FIFO 顺序调度,优先级队列可实现高优先级任务优先执行。
  3. 广度优先搜索(BFS):算法中用于层级遍历(如二叉树层序遍历、迷宫最短路径求解)。
  4. 消息队列:多线程 / 多进程间的通信机制,实现数据的异步传递。
相关推荐
say_fall1 小时前
C语言编程实战:每日一题:有效的括号
c语言·开发语言·数据结构·
张张努力变强1 小时前
二叉树——精选题目,体验递归的暴力美学!
c语言·数据结构·算法
BD_Marathon1 小时前
【Java】集合里面的数据结构
java·数据结构·python
FMRbpm1 小时前
栈练习--------(LeetCode 739-每日温度)
数据结构·c++·算法·leetcode·新手入门
子一!!1 小时前
数据结构==二叉平衡树,AVL树 ===
数据结构·算法
山峰哥1 小时前
从指针到智能体:我与C++的二十年技术进化与AI革命
大数据·开发语言·数据结构·c++·人工智能
youngee111 小时前
hot100-44从前序与中序遍历构造二叉树
数据结构·算法
im_AMBER1 小时前
Leetcode 68 搜索插入位置 | 寻找比目标字母大的最小字母
数据结构·笔记·学习·算法·leetcode
hweiyu001 小时前
数据结构:红黑树
数据结构