数据结构-如何实现一个队列?逐步解析与代码示例(超详细)

这篇具有很好参考价值的文章主要介绍了数据结构-如何实现一个队列?逐步解析与代码示例(超详细)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

数据结构-如何实现一个队列?逐步解析与代码示例(超详细),数据结构,链表

前言

在计算机科学中,队列是一种非常基础且广泛使用的数据结构。它的工作原理类似于现实生活中的排队:先来的先服务(FIFO, First-In-First-Out)。在本文中,我们将深入探讨如何在C语言中使用链表实现一个队列,并解析相关的代码实现。


1.队列的基本概念

队列是一种遵循先进先出原则的线性数据结构。在队列中,添加操作(入队)发生在一端(队尾),而移除操作(出队)则发生在另一端(队首)。这种结构在多种场景中非常有用,如任务调度、数据缓冲等。
数据结构-如何实现一个队列?逐步解析与代码示例(超详细),数据结构,链表


2.链表与数组实现队列的区别

当使用数组和链表实现队列时,主要区别在于数据存储结构、性能和内存使用:

2.1数据存储结构

数组:队列使用一个固定大小的数组。当数组满时,需要进行扩容,这可能涉及复制整个数组到新的内存位置。
链表:队列使用动态分配的节点,每个节点包含数据和指向下一个节点的指针。不需要事先分配固定大小的空间。

2.2性能

数组:入队和出队操作通常是O(1)复杂度,但当数组需要扩容时,复杂度会增加。
链表:由于不需要扩容,入队和出队操作始终保持O(1)复杂度。

2.3内存使用

数组:可能会有未使用的预留空间,特别是在队列大小波动较大时。
链表:每个元素单独分配,无需预留额外空间,但每个节点需要额外存储指针,略增加内存使用。


3.为什么选择链表实现队列?

在C语言中,链表是一种常用的数据结构,用于创建动态大小的序列。相比于数组实现,链表实现的队列具有动态分配内存的优点,不受固定大小的限制。

与基于数组的队列实现相比,链表实现的队列具有以下优势:

动态大小:不受固定长度的限制,可以根据需要动态扩展或收缩。
内存利用:每个元素仅在需要时分配内存,减少了空间浪费。
性能优化:避免了数组实现中可能发生的元素搬移操作。

接下来我们来用链表进行实现队列。


4.结构定义

该队列的实现基于两种结构:QueueNode 和 Queue。

typedef int QDataType; // 定义队列数据类型为int

// 队列节点的结构体定义
typedef struct QueueNode
{
  QDataType val; // 节点存储的数据
  struct QueueNode* next; // 指向下一个节点的指针
} QNode;

// 队列的结构体定义
typedef struct Queue
{
  QNode* phead; // 指向队列头部的指针
  QNode* ptail; // 指向队列尾部的指针
  int size; // 队列的大小
} Queue;

这里,QueueNode 表示队列中的每个节点,包含一个数据字段和一个指向下一个节点的指针。而Queue结构则持有指向队列头部和尾部的指针,并跟踪队列的当前大小。

函数声明

// 函数声明
void QInit(Queue* pq); // 初始化队列
void QDestroy(Queue* pq); // 销毁队列

void QPush(Queue* pq, QDataType x); // 向队列中添加元素
void QPop(Queue* pq); // 从队列中移除元素

QDataType QueueFront(Queue* pq); // 获取队列头部元素
QDataType QueueBack(Queue* pq); // 获取队列尾部元素

bool QueueEmpty(Queue* pq); // 检查队列是否为空
int QueueSize(Queue* pq); // 获取队列的大小

5.核心操作

5.1初始化 (QInit)

初始化函数设置队列的头部和尾部指针为NULL,大小为0。这是创建队列的必要步骤。
数据结构-如何实现一个队列?逐步解析与代码示例(超详细),数据结构,链表

// 初始化队列
void QInit(Queue* pq)
{
  assert(pq); // 断言队列指针非空
  pq->phead = pq->ptail = NULL; // 将头指针和尾指针都设为NULL
  pq->size = 0; // 将队列大小设置为0
}

5.2销毁 (QDestroy)

销毁函数释放队列中所有节点的内存,并重置队列的状态。这是队列不再使用时的清理步骤。
数据结构-如何实现一个队列?逐步解析与代码示例(超详细),数据结构,链表

// 销毁队列
void QDestroy(Queue* pq)
{
  assert(pq); // 断言队列指针非空
  QNode* cur = pq->phead;
  while (cur)
  {
    QNode* next = cur->next; // 保存下一个节点
    free(cur); // 释放当前节点
    cur = next; // 移动到下一个节点
  }
  pq->phead = NULL; // 将头指针设为NULL
  pq->ptail = NULL; // 将尾指针设为NULL
  pq->size = 0; // 将队列大小设置为0
}

5.3入队 (QPush)

在队列的尾部添加一个新元素。如果队列为空,则新元素同时成为头部和尾部元素。
数据结构-如何实现一个队列?逐步解析与代码示例(超详细),数据结构,链表

// 向队列中添加元素
void QPush(Queue* pq, QDataType x)
{
  assert(pq); // 断言队列指针非空
  QNode* newNode = (QNode*)malloc(sizeof(QNode)); // 分配新节点内存
  if (newNode == NULL)
  {
    perror("malloc fail"); // 内存分配失败处理
    exit(-1);
  }

  newNode->val = x; // 设置新节点的值
  newNode->next = NULL; // 新节点的下一个节点为NULL
  if (pq->ptail == NULL) // 如果队列为空
  {
    pq->phead = pq->ptail = newNode; // 队列头尾都指向新节点
  }
  else
  {
    pq->ptail->next = newNode; // 将新节点接到队列尾部
    pq->ptail = newNode; // 更新尾指针
  }
  pq->size++; // 队列大小增加
}

5.4出队 (QPop)

从队列的头部移除一个元素。如果队列为空,调整尾部指针。
数据结构-如何实现一个队列?逐步解析与代码示例(超详细),数据结构,链表

// 从队列中移除元素
void QPop(Queue* pq)
{
  assert(pq); // 断言队列指针非空
  assert(pq->phead); // 断言队列不为空
  QNode* Del = pq->phead; // 保存要删除的节点
  pq->phead = pq->phead->next; // 更新头指针
  free(Del); // 释放节点内存
  if (pq->phead == NULL) // 如果队列变空
  {
    pq->ptail = NULL; // 更新尾指针
  }
  pq->size--; // 队列大小减少
}

6.队列的查询操作

6.1队首元素 (QueueFront)

返回队列头部节点的值,但不移除它。
数据结构-如何实现一个队列?逐步解析与代码示例(超详细),数据结构,链表

// 获取队列头部元素的值
QDataType QueueFront(Queue* pq)
{
  assert(pq); // 断言队列指针非空
  assert(pq->phead); // 断言队列不为空
  return pq->phead->val; // 返回头部元素的值
}

6.2队尾元素 (QueueBack)

返回队列尾部节点的值。
数据结构-如何实现一个队列?逐步解析与代码示例(超详细),数据结构,链表

// 获取队列尾部元素的值
QDataType QueueBack(Queue* pq)
{
  assert(pq); // 断言队列指针非空
  assert(pq->ptail); // 断言队列不为空
  return pq->ptail->val; // 返回尾部元素的值
}

7.辅助函数

7.1判断空 (QueueEmpty)

检查队列是否为空。
数据结构-如何实现一个队列?逐步解析与代码示例(超详细),数据结构,链表

// 检查队列是否为空
bool QueueEmpty(Queue* pq)
{
  assert(pq); // 断言队列指针非空
  return pq->phead == NULL; // 如果头指针为NULL,则队列为空
}

7.2队列大小 (QueueSize)

返回队列中节点的数量。
数据结构-如何实现一个队列?逐步解析与代码示例(超详细),数据结构,链表

// 获取队列的大小
int queueSize(Queue* pq)
{
  return pq->size; // 返回队列的大小
}


总结

理解队列的不同实现方式对于选择最适合特定应用场景的数据结构至关重要。链表实现的队列提供了灵活性和一致的性能,特别适用于大小不确定或需要频繁扩展的场景。而数组实现则在空间预分配和随机访问方面更有优势。深入了解这些差异,可以帮助程序员做出更明智的选择。我希望这篇文章能够帮助你更好地理解和实现队列。如果你有任何问题或想分享你的经验,请在评论区留言。文章来源地址https://www.toymoban.com/news/detail-768152.html

到了这里,关于数据结构-如何实现一个队列?逐步解析与代码示例(超详细)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构——队列的实现

    队列 ,又称为伫列(queue),计算机科学中的一种抽象资料类型,是先进先出(FIFO, First-In-First-Out)的线性表。在具体应用中通常用链表或者数组来实现。队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作。 这段代码使用 typedef 定义了一个

    2024年02月10日
    浏览(34)
  • 【数据结构】:队列的实现

    队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头 队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如

    2024年02月07日
    浏览(36)
  • 【数据结构】队列的实现

    队列是一种常用的数据结构,也是一种操作受限制的线性表,特点是只允许在表的头部进行删除操作,在表的尾部进行插入操作,队列具有先进先出FIFO(First In First Out)。 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头 我们实现可以用数组和链表

    2024年02月02日
    浏览(37)
  • 【数据结构—队列的实现】

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一、队列 1.1队列的概念及结构 二、队列的实现 2.1头文件的实现—Queue.h 2.2源文件的实现—Queue.c 2.3源文件的测试—test.c 三、测试队列实际数据的展示 3.1正常队列的出入 3.2入队列的同时存

    2024年02月04日
    浏览(40)
  • 数据结构---队列的实现

    前言 一、什么是队列? 二、 队列接口的实现 1. 队列结构的定义 2. 接口实现 总结 队列是一种特殊的线性表。 特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。 进行插入操作的端称为

    2024年02月02日
    浏览(33)
  • 数据结构—队列的实现

    前言:上次我们已经学习了数据结构中一个重要的线性表—栈,那么我们这一次就来学习另外一个重要的线性表—队列。 一、 队列的概念 二、 队列的实现: 1.队列的创建 三、 队列的操作 1.初始化队列 2.队尾入队列 3.队头出队列 4.获取队列头部元素 5.获取队列队尾元素 6.获

    2024年02月04日
    浏览(36)
  • 【数据结构】队列及其实现

    目录 😎前言 认识队列 队列的初始化 队列判空 数据队尾入队 数据队头出队 取队头数据 取队尾数据 队列数据的个数 队列销毁 总结 上次我们学习了栈及其实现,当然也少不它的好兄弟队列啦,今天我们开始队列的学习 队列的性质是 先进先出 ,就比如车辆进出隧道一般,它

    2024年02月09日
    浏览(43)
  • 数据结构 | 队列的实现

    队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头 队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如

    2024年02月05日
    浏览(41)
  • 【数据结构】如何设计循环队列?图文解析(LeetCode)

    LeetCode链接:622. 设计循环队列 - 力扣(LeetCode) 目录 做题思路 只开辟 k 个空间 多开一个空间 代码实现 1. 循环队列的结构 2. 开辟空间 3. 判断空 4. 判断满 5. 队尾插入数据 6. 队头删除数据 7. 获取队头元素 8. 获取队尾元素 9. 销毁队列 全部代码 设计循环队列,使用数组或链表

    2024年02月10日
    浏览(42)
  • 【数据结构与算法】用队列实现栈&&用栈实现队列&&设计循环队列

    🌠 作者:@ 阿亮joy. 🎆 专栏:《数据结构与算法要啸着学》 🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、

    2024年01月20日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包