数据结构与算法(C语言版)P6---队列

1、队列的概念及结构

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

入队列:进行插入操作的一端称为__队尾__。

出队列:进行删除操作的一端称为__对头__。

在这里插入图片描述
数据存放:现在有数据:A、B、C、D要存放,那存放数据顺序就是一次存入,并且存放的位置如下:
在这里插入图片描述

1.1、队列的实现概念

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果数组的结构,出队列在数组头上出数据,效率会比较低。

因为数组队列在处一个数据后们需要整体挪动数据向前,所以麻烦,这里不如链表。而链表在出数据是,把节点释放,然后将phead在指向要出数据的后一个数据即可,并且我们也记录个尾节点ptail,用来链接放在队列中新数据即可。

在这里插入图片描述
所以队列的实现主要以链表队列为主要。

2、链队列的实现

队列主要有以下接口函数

  • 初始化(QueueInit)
  • 销毁(QueueDestroy)
  • 扩容(BuyQueueNode)
  • 队尾插入数据(QueuePush)
  • 对头删除数据(QueuePop)
  • 取队尾数据(QueueBack)
  • 取对头数据(QueueFront)
  • 统计队列中数据个数(QueueSize)
  • 判断队列是否为空(QueueEmpty)

2.1、定义结构体

这里需要重点说明这个结构体的定义。
1、首先我们定义一个QueueNode结构体,这个结构体就是动态扩容的结点。里面有一个Next指针域,还有一个data数据域。如下:

typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QNode;

2、然后是重点来了:这里我们需要创建两个QueueNode*类型的指针:head,tail。分别用来队列的头结点和尾节点。如下:

typedef struct Queue
{struct QueueNode* head;struct QueueNode* tail;
}Queue;

然后整体结构体定义就如下:

#pragma once#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>typedef int QDataType;typedef struct QueueNode
{QDataType data;struct QueueNode* Next;
}QNode;typedef struct Queue
{struct QueueNode* head;struct QueueNode* tail;
}Queue;

2.2、队列初始化

将头结点和尾节点置为NULL即可。

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

2.3、销毁

依次遍历结点进行销毁

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

2.4、扩容

//扩容
QNode* BuyQueueNode(QDataType x)
{QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){printf("malloc fail\n");exit(-1);}newnode->data = x;newnode->Next = NULL;return newnode;
}

2.5、队尾插入数据

队列在队尾入数据,因为我们提前设置了尾结点(tail),那操作就容易了,先将tail的Next域指向新节点的地址,然后再将新节点的地址赋值给tail,便于下次再尾插。

但是由于我们没创建哨兵位,所以在进行结点的插入和删除时,需要考虑边界问题。
那这里,特殊情况就是,如果是第一次插入数据,也就是当pq->head == NULL时,我们可以直接将新节点的地址赋值给头结点和尾节点。

//对尾插入数据
void QueuePush(Queue* pq, QDataType x)
{QNode* newnode = BuyQueueNode(x);if (pq->head == NULL){pq->head = pq->tail = newnode;}else{pq->tail->Next = newnode;pq->tail = newnode;}
}

2.6、对头删除数据

核心思想:先保存头结点的后驱结点的地址,然后释放头结点,然后将先前保存头结点的后驱结点的地址赋值给头结点。
特殊情况:当pq->head == NULL时,也就意味着整个队列为空了,所以我们还需要将pq->tail = NULL。

//队头删除数据
void QueuePop(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));QNode* next = pq->head->Next;free(pq->head);pq->head = next;if (pq->head == NULL){pq->tail = NULL;}
}

2.7、取队尾数据

//取队尾数据
QDataType QueueBack(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->tail->data;
}

2.8、取对头数据

//取对头数据
QDataType QueueFront(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->head->data;
}

2.8、统计队列元素个数

使用个计数器,依次遍历队列中的结点,来统计队列元素个数。

//统计队列元素个数
int QueueSize(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));int count = 0;QNode* cur = pq->head;while (cur){count++;cur = cur->Next;}return count;
}

2.10、判断队列是否为空

//判断队列是否为空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->head == NULL;
}

2.11、main函数测试程序

下面测试程序功能:遍历输出队列中的数据。

#include "queue.h"int main()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);QueuePush(&q, 5);QueuePush(&q, 6);while (!QueueEmpty(&q)){printf("%d ", QueueFront(&q));QueuePop(&q);}printf("\n");QueueDestroy(&q);return 0;
}

输出:
在这里插入图片描述

3、全代码展示

这里使用三个文件:

  • queue.h:用于结构体、各种函数接口的声明
  • queue.c:用于各种函数接口的定义。
  • test.c:用于创建链表,实现链表。

3.1、queue.h

#pragma once#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>typedef int QDataType;typedef struct QueueNode
{QDataType data;struct QueueNode* Next;
}QNode;typedef struct Queue
{struct QueueNode* head;struct QueueNode* tail;
}Queue;//队列初始化
void QueueInit(Queue* pq);//销毁
void QueueDestroy(Queue* pq);//扩容
QNode* BuyQueueNode(QDataType x);//对尾插入数据
void QueuePush(Queue* pq, QDataType x);//队头删除数据
void QueuePop(Queue* pq);//取队尾数据
QDataType QueueBack(Queue* pq);//取对头数据
QDataType QueueFront(Queue* pq);//统计队列元素个数
int QueueSize(Queue* pq);//判断队列是否为空
bool QueueEmpty(Queue* pq);

3.2、queue.c

#include "queue.h"//队列初始化
void QueueInit(Queue* pq)
{assert(pq);pq->head = NULL;pq->tail = NULL;
}//销毁
void QueueDestroy(Queue* pq)
{assert(pq);QNode* cur = pq->head;while (cur){QNode* next = cur->Next;free(cur);cur = next;}pq->head = pq->tail = NULL;
}//扩容
QNode* BuyQueueNode(QDataType x)
{QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){printf("malloc fail\n");exit(-1);}newnode->data = x;newnode->Next = NULL;return newnode;
}//对尾插入数据
void QueuePush(Queue* pq, QDataType x)
{QNode* newnode = BuyQueueNode(x);if (pq->head == NULL){pq->head = pq->tail = newnode;}else{pq->tail->Next = newnode;pq->tail = newnode;}
}//队头删除数据
void QueuePop(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));QNode* next = pq->head->Next;free(pq->head);pq->head = next;if (pq->head == NULL){pq->tail = NULL;}
}//取队尾数据
QDataType QueueBack(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->tail->data;
}//取对头数据
QDataType QueueFront(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->head->data;
}//统计队列元素个数
int QueueSize(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));int count = 0;QNode* cur = pq->head;while (cur){count++;cur = cur->Next;}return count;
}//判断队列是否为空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->head == NULL;
}

3.3、test.c

#include "queue.h"int main()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);QueuePush(&q, 5);QueuePush(&q, 6);while (!QueueEmpty(&q)){printf("%d ", QueueFront(&q));QueuePop(&q);}printf("\n");QueueDestroy(&q);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/88516.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Cpp/Qt-day040920Qt

目录 时钟 头文件&#xff1a;Widget.h: 源文件:Widget.c: 效果图&#xff1a; 思维导图 时钟 头文件&#xff1a;Widget.h: #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPaintEvent> #include <QPainter> #include <QTime>…

性能测试 —— 性能测试常见的测试指标 !

一、什么是性能测试 先看下百度百科对它的定义&#xff0c;性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。 我们可以认为性能测试是&#xff1a;通过在测试环境下对系统或构件的性能进行探测&#xff0c;用以验证在生产环…

安防视频/集中云存储平台EasyCVR(V3.3)部分通道显示离线该如何解决?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

it运维监控主要做什么

IT运维监控已成为企业经营的重要组成部分。为了保证全面高效的运行&#xff0c;提升企业的经营效率和服务水平&#xff0c;主要从事对企业的IT基础设施进行监控和管理。所以&#xff0c;IT运维监控的关键是什么&#xff1f; IT运维监控的主要任务是确保IT基础设施的正常使用。它…

Gitee使用用户名密码登录一直错误/IDEA连接gitee仓库密码错误

天坑,注册的时候名字带了大写,用户名自动给你变成小写 真正的用户名在个人主页里面看,是后面的字符,才是真正的用户名.排查了一个小时密码问题,真的坑

百度SEO优化不稳定的原因分析(提升网站排名的稳定性)

百度SEO优化不稳定介绍蘑菇号-www.mooogu.cn SEO不稳定是指网站在搜索引擎中的排名不稳定&#xff0c;随着时间的推移会发生变化。这种情况可能会出现在网站页面结构、内容质量、外链质量等方面存在缺陷或不合理之处。因此&#xff0c;优化SEO非常重要&#xff0c;可以提高网站…

Gateway网关

网关GateWay 官方文档&#xff1a;https://docs.spring.io/spring-cloud-gateway/docs/3.1.2/reference/html/#gateway-how-it-works 核心概念 路由: 网关的核心数据结构&#xff0c;定义了网关如何处理请求. 一条路由信息包含路由的唯一标识ID,目的地URI, 一组断言&#xf…

融云 CallPlus + X,通话场景一站式解决方案

融云近期上线的 CallPlus SDK&#xff0c;针对音视频呼叫场景单独设计后端服务 Call Server&#xff0c;信令延时低至 150ms&#xff0c;确保各端计时准确、一致&#xff1b;上线了音视频通话互转、灵活的多人通话、通话记录管理能力等功能。关注【融云全球互联网通信云】了解更…

regsvr32 initpki.dll找不到指定模块要怎么解决?教你快速修复initpki.dll文件

当你尝试在 Windows 操作系统中注册 DLL 文件时&#xff0c;可能会遇到错误消息&#xff1a;“regsvr32 initpki.dll找不到指定模块”。它通常是由于一个或多个 DLL 文件缺失或损坏所导致的。这是一个常见的错误&#xff0c;并且可以遇到在 Windows 7、Windows 8 和 Windows 10…

点餐小程序的制作流程详解

随着移动互联网的发展&#xff0c;越来越多的消费者开始使用手机进行点餐&#xff0c;这也促使了点餐小程序的兴起。如果您是一位商家&#xff0c;想要开发一个属于自己的点餐小程序&#xff0c;那么不妨尝试一下以下的DIY教程吧&#xff01; 首先&#xff0c;我们需要找一个专…

Android存储权限完美适配(Android11及以上适配)

一、Bug简述 一个很普通的需求&#xff0c;需要下载图片到本地&#xff0c;我的三个测试机&#xff08;荣耀Android10&#xff0c;红米 11 和小米Android 13都没有问题&#xff09;。 然后&#xff0c;主角登场了&#xff0c;测试的三星Android 13 死活拉不起存储权限弹窗。 …

【文件操作——详细讲解】

1. 为什么使用文件&#xff1f;&#x1f9d0; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数…

H3C ER G2系列路由器敏感信息泄露漏洞

声明 本文仅用于技术交流&#xff0c;请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任。 一、产品介绍 H3C ER2200G2是H3C推出的新一代高性能企业级路由器&#…

NPDP证书,为什么这么多人考?

NPDP证书至2016年引进国内&#xff0c;考试人数就持续增长&#xff0c;不仅是新产品开发唯一 的职业证书&#xff0c;在产品管理这一领域的知名度也在前列&#xff0c;那么这个证书的作用在哪里呢&#xff1f; 想考npdp证书&#xff0c;npdp干货可下载&#xff1a; 1、就业范围…

腾讯云最新优惠活动有哪些?活动入口在哪里?

腾讯云作为国内知名的云计算服务提供商&#xff0c;为了吸引用户&#xff0c;经常推出各种优惠活动。以下是近期腾讯云的一些优惠活动及其入口&#xff1a; 一、腾讯云新用户优惠券【点此领取】 腾讯云新用户专属大礼包&#xff0c;无门槛领取总价值高达2860元代金券&#xff…

手把手教你,细说向开源项目递交代码的流程

系列文章目录 手把手教你安装Git&#xff0c;萌新迈向专业的必备一步 GIT命令只会抄却不理解&#xff1f;看完原理才能事半功倍&#xff01; 常用GIT命令详解&#xff0c;手把手让你登堂入室 GIT实战篇&#xff0c;教你如何使用GIT可视化工具 GIT使用需知&#xff0c;哪些操作…

亚信科技AntDB数据库 高并发、低延迟、无死锁,深入了解AntDB-M元数据锁的实现

AntDB-M在架构上分为两层&#xff0c;服务层和存储引擎层。元数据的并发管理集中在服务层&#xff0c;数据的存储访问在存储引擎层。为了保证DDL操作与DML操作之间的一致性&#xff0c;引入了元数据锁&#xff08;MDL&#xff09;。 AntDB-M提供了丰富的元数据锁功能&#xff0…

c语言-实用调试技巧

什么是bug&#xff1f; 程序中出现的问题 调试是什么&#xff1f;有多重要&#xff1f; 测试的基本步骤&#xff1a;发现程序错误的存在 以隔离、消除等方式对错误进行定位&#xff0c;确定错误产生的原因&#xff0c;提出纠正错误的解决办法&#xff0c;对程序错误予以改正…

云原生之使用Docker部署RSS阅读器Huntly

云原生之使用Docker部署RSS阅读器Huntly 一、Huntly介绍1.1 Huntly简介1.2 Huntly功能2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载Huntly镜像五、部署Huntly5.1 创建挂载目录5.2 创建Hun…

气导耳机是什么样的?盘点五款好用的气传导耳机分享

​气传导耳机在运动、户外、办公等场景中具有独特的优势。然而&#xff0c;面对市场上琳琅满目的气传导耳机产品&#xff0c;很多用户不知如何下手。接下来&#xff0c;我将推荐市面上热销火爆&#xff0c;并性能出色、性价比高的气传导耳机给大家&#xff0c;希望大家都能选到…