什么是队列,如何实现?

简介: 什么是队列,如何实现?

image.png“海色温柔,波浪缓慢,似乎在静静期待着新的一天。”


前言:

上期我们讲了栈,它的特点是“后入先出”。这次我们再来学习一个新的数据结构:队列,它的特点是“先入先出,后入后出”,准备好了吗?开始!



Part1: 何为队列 


1.队列的概念


队列队列,顾名思义,就像排队买饭,排在前面的人买到饭先走,排到后面的人需要等待... ...

下面是队列的正经概念:

只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出原则(First In First Out) 。

进行插入操作的一端称为队尾,

进行删除操作的一端称为队头。


2.队列的结构

f10fe1d3e57ce60f21d73ef5b9df2486_08587406682c44649f30e61fe9b3cb41.png

我是图示 



Part2: 队列的实现


1.前期准备


1.1创建项


不解释:

Queue.h:头文件,声明所有函数;

Queue.c:源文件,实现各函数;

Test.c:  源文件,主函数所在项,可调用各函数。


1.2队列结构


仍然是那个问题:用什么结构来实现队列较好?

数组:?删除元素要整体移动,时间复杂度高,且动态扩容比较麻烦,不推荐;

链表:插入删除数据后无需修改中间部分的元素,方便在队头和队尾操作,推荐。

那么选双链表还是单链表呢?

若选择双链表,的却方便找尾,但是仅仅为了找尾方便而选择它,未免会显得臃肿;

选择单链表呢,轻巧简洁,只需解决找到尾部的问题即可,有一个巧妙的方法就是:

在队列的结构中 定义尾指针

我们捋一遍:

就队列的整体来说:需要首尾指针和大小(长度);

就队列中的一个结点来说:需要下一个结点的指针和要存储的数据。

欸?相比栈来说,是不是结构更加复杂了?

是的,这意味着要多定义一个结构体,两个结构体之间是包含关系:

fb10ddf48850507c0eac2b7174625754_4d897f35e7d1466db5f0fbbd07e1caf9.png

我是图示 

上代码:

typedef int QDataType;
//队列中的结点
typedef struct QListNode
{
  struct QListNode* next;
  QDataType data;
}QNode;
//队列整体
typedef struct Queue
{
  QNode* head;
  QNode* tail;
  int size;
}Queue;


1.3队列初始化


要从整体上把握,把首尾指针初始化为空,大小初始化为 0 即可:

// 初始化队列
void QueueInit(Queue* pq)
{
  assert(pq);
  pq->head = pq->tail = NULL;
  pq->size = 0;
}


2.功能实现


2.1队头出队列


队头出队列,队列中是一定至少有一个结点的,但其实还是要分两种情况考虑的:

一是只有一个结点,直接把这个结点释放掉,再将首尾置空即可;

二是有两个及以上个结点,除了释放头部的结点,还需要把队头指针指向下一个结点;

最后莫忘大小减一。

// 队头出队列
void QueuePop(Queue* pq)
{
  assert(pq);
  assert(pq->head);
  if (pq->head->next == NULL)
  {
    free(pq->head);
    pq->head = pq->tail = NULL;
  }
  else
  {
    QNode* next = pq->head->next;
    free(pq->head);
    //pq->head = NULL;
    pq->head = next;
  }
  pq->size--;
}


2.2队尾入队列

要入队列,首先要先申请一个新的结点(注意是结点,不是队列);

再申请完并初始化后,就需要插入了:

也是两种情况:

一是链表为空,此时只要将首尾指针修改为新结点指针即可;

二是链表不为空,就要用到尾指针,将尾结点的下一个结点修改为新结点,并且更新尾结点指针;

最后莫忘大小加一。

// 队尾入队列
void QueuePush(Queue* pq, QDataType x)
{
  assert(pq);
  QNode* tailNode = (QNode*)malloc(sizeof(QNode));
  if (tailNode == NULL)
  {
    perror("malloc fail");
    return;
  }
  tailNode->next = NULL;
  tailNode->data = x;
  if (pq->head == NULL)
  {
    pq->head = pq->tail = tailNode;
  }
  else
  {
    pq->tail->next = tailNode;
    pq->tail = tailNode;//掉
  }
  pq->size++;
}


2.3获取队列头部元素


进行了插入操作,当然要看看数据怎么样啦

这个比较简单,直接返回头部数组即可

// 获取队列头部元素
QDataType QueueFront(Queue* pq)
{
  assert(pq);
  assert(pq->head && pq->tail);
  return pq->head->data;//NULL
}


2.4获取队列尾部元素


同上:

// 获取队列队尾元素
QDataType QueueBack(Queue* pq)
{
  assert(pq);
  assert(pq->head && pq->tail);
  return pq->tail->data;
}


2.5获取队列中有效元素个数


还记得之前定义的 size 吗?

在这里它就展现出重要作用了:

// 获取队列中有效元素个数
int QueueSize(Queue* pq)
{
  assert(pq);
  return pq->size;
}


2.6判断队列是否为空


为空返回非 0 ,不是空就返回 0;

// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* pq)
{
  return pq->size == 0;
}


2.7销毁队列


思路就是把整个队列遍历一遍,释放每个结点,再把首尾指针置空,大小归 0 即可:

// 销毁队列
void QueueDestroy(Queue* pq)
{
  assert(pq);
  QNode* cur = pq->head;
  while (cur)
  {
    free(cur);
    cur = cur->next;
  }
  pq->head = pq->tail = NULL;
  pq->size = 0;
}

总结:

其实相比栈来说,队列只是在结构上复杂了一些,其他的操作与单链表的操作就非常相似了。

目录
相关文章
|
Web App开发 Oracle Java
如何优雅地安装 Android Studio
如何优雅地安装 Android Studio
382 0
|
Web App开发 移动开发 JavaScript
彻底学会快速部署vue框架,一篇就够了
Vue框架诞生于2014年,其作者为中国人——尤雨溪,也是新人最容易入手的框架之一,不同于React和Angular,其中文文档也便于大家阅读和学习。Vue用于构建交互式的Web界面的库,是一个用于构建用户界面的渐进式框架。
1757 0
彻底学会快速部署vue框架,一篇就够了
|
8月前
|
缓存 编解码 监控
开发体育直播系统:用户管理机制与内容审核技术实现方案
本体育赛事直播系统基于ThinkPHP框架构建管理端,实现内容审核、用户管理和权限配置等功能。系统通过角色与权限设计(如普通用户、主播、专家等),结合JWT认证和多端统一登录方案,确保安全性和灵活性。内容管理方面,采用敏感词过滤、自动化审核及阿里云内容安全服务,保障直播质量。性能优化涵盖推流鉴权、H.265编码和缓存策略,提升用户体验。此外,系统还提供实时监控看板与用户行为分析,支持粘性分析和智能推荐,全方位满足体育直播需求。
|
12月前
|
运维 前端开发 C#
一套以用户体验出发的.NET8 Web开源框架
一套以用户体验出发的.NET8 Web开源框架
321 7
一套以用户体验出发的.NET8 Web开源框架
|
11月前
|
Oracle 关系型数据库 Linux
linux8安装oracle 11g遇到的问题记录
Oracle 11g在Linux 8上安装时会遇到link编译环节的问题。官方建议忽略安装中的链接错误,安装完成后应用DBPSU 11.2.0.4.240716补丁及一次性补丁33991024,再重新编译二进制文件,并配置监听器和数据库。但因11g已退出服务期,这些补丁需付费获取。网上信息显示22年1月的PSU补丁也可解决问题,找到该补丁后按常规方式打补丁即可。如有需求或疑问可咨询我。
508 20
|
网络协议 算法 网络性能优化
|
存储 人工智能 安全
《C++ 人工智能模型邂逅云平台:集成之路的策略与要点全解析》
在数字化时代,C++凭借其高性能和资源效率,成为开发人工智能模型的重要工具。云平台则提供强大的计算能力、灵活的存储及便捷的服务部署,为AI模型的应用拓展创造条件。本文探讨了C++与云平台集成的关键策略,包括云平台选型、数据管理、模型部署、性能优化及安全防护,旨在构建高效、稳定的AI应用系统,推动技术革新。
170 13
|
网络协议
通俗易懂理解三次握手、四次挥手(TCP)
这篇文章用通俗的语言解释了TCP协议中的三次握手和四次挥手过程,通过比喻和详细的状态变化描述,帮助读者理解建立和断开连接的原理和原因。
通俗易懂理解三次握手、四次挥手(TCP)
|
Dragonfly 安全 算法