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

数据结构--队列与循环队列的实现

数据结构–队列的实现

1.队列的定义

比如有一个人叫做张三,这天他要去医院看病,看病时就需要先挂号,由于他来的比较晚,所以他的号码就比较大,来的比较早的号码就比较小,需要到就诊窗口从小号到大依次排队,前面的小号就诊结束之后,才会轮到大号来,小号每就诊完毕就销毁,每新来一个病人就会顺着向后增加一个较大的号码,这些号码就构成了队列.

所谓队列就是一种先进先出的数据结构,例如在例子中,先来挂号的病人先就诊,后来的病人后就诊,队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表,队列是一种先进先出的线性表,允许插入数据的一端称之为队尾,允许删除数据的一端称之为队头.**假设队列中的元素是{a,b,c,d,e,f,g}那么a就是队头元素,g就是队尾元素,这样删除时就可以总是从a处开始,插入数据时从g开始,也比较符合我们的日常生活习惯.

在这里插入图片描述

队列在生活中的使用非常频繁.

2.队列的实现

队列实际上也是线性表,但是队列的操作与栈是不同的,队列的对于数据的插入操作是在队尾进行的,对数据的删除操作是在队头进行,那么由此可以想到,对于有这种特点的队列,使用链表的结构更加方便,因为链表的头删和尾插的效率非常高,不需要像数组那样挪动数据.

2.1节点的定义

每个节点需要存储数据和下一个节点的地址.

typedef struct QueueNode//此处定义的是每个节点的结构
{struct QueueNode* next;QDataType data;
}QueueNode;

由于我们是对每个节点之间的链接关系进行处理,所以就需要定义结构体的指针对节点中的next指针进行操作,所以我们可以定义head和tail两个结构体指针,head指针指向链表的第一个节点,tail指针指向链表的最后一个节点.那么就可以将这两个节点也包装成一个结构体:

typedef struct Queue//将两个指针包装成一个结构体
{QueueNode* head;QueueNode* tail;
}Queue;

在这里插入图片描述

2.2队列的初始化

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

2.3判断队列是否为空

bool QueueEmpty(Queue* pq)
{assert(pq);return pq->head == NULL;
}

2.4队列的销毁

void QueueDestroy(Queue* pq)
{assert(pq);QueueNode* cur = pq->head;//while (cur != NULL){QueueNode* next = cur->next;free(cur);cur = next;}pq->head = pq->tail = NULL;
}

2.5插入数据

void QueuePush(Queue* pq, QDataType x)//插入数据
{assert(pq);QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){printf("malloc fail!");exit(0);}newnode->data = x;newnode->next = NULL;if (pq->head == NULL){pq->head = pq->tail = newnode;}else{pq->tail->next = newnode;//连接两个节点pq->tail = newnode;//新的尾节点}
}

2.6删除队头数据

删除队头数据之前要判断队列是否为空队列,如果队列是空队列就无法进行删除操作.

void QueuePop(Queue* pq)//删除数据
{assert(!QueueEmpty(pq));//队列不能为空QueueNode* next = pq->head->next;free(pq->head);pq->head = next;//假如链表已经被删完了,此刻要将tail也置为空指针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.9获取队列的节点的个数

int QueueSize(Queue* pq)
{assert(pq);int n = 0;QueueNode* cur = pq->head;while (cur != NULL){n++;cur = cur->next;}return n;
}

3.循环队列

3.1循环队列的设计

  1. 假定我们是使用的数组实现队列.那么假设一个队列含有n个元素,我们就需要创建一个元素个数大于n的数组.并将队列中的数据存储在数组的前n个单元,数组下标为0的一端就是队头,另一端就是队尾.
  2. 为了方便,我们设置两个变量,一个front用于存储队头数据的下标,也就是0,另一个rear变量用于存储队尾的元素的下一个位置.当需要取出队头元素时,就需要除了队头之外的所有数据都需要向前移动一格.

在这里插入图片描述

  • 由此看来,效率是不高的,所以这里可以改进,让front指针移动起来,队头每出一个元素,front就向后移动一个单位.

在这里插入图片描述

  • 假设数组一开始是空的,那么front和rear一开始的值就都是0,每插入一个元素,rear就向后移动.

在这里插入图片描述

  • 但是此时的rear就移动到了数组之外的空间了,假如此刻数组中的数据都已经满了,然而继续向其中插入数据,就出现了越界问题.

假如是以下这种情况呢??
在这里插入图片描述

  • 此刻向rear位置插入数据之后,此时的数组的0和1位置处是空的,那此时rear若再向后加,就显得有点蠢了,因为数组中的前面是空着的却不用.

解决办法:当rear快越界时,接着让rear从数组的第一个元素开始,构成循环,这就是循环队列.例如在下面这种情况,将rear改为0时比较好的.
在这里插入图片描述

那此刻我们接着向队列中插入元素.
在这里插入图片描述

  • 不难发现,当队列满了之后,rear和front是指向同一个下标的(即rear == front).在队列为空时,rear和front指向的是同一个下标(rear == front),那么什么情况队列是满什么情况队列是空就无法确切的判断了.

解决方案:当队列为空时,条件是rear == front,当队列为满时,保留一个元素的空间,在数组中留一个空闲单元,如下图所示,此刻的队列就已经满了.假设数组的最大容量是N个单位,那么队列为满的条件就是 (rear+1)%N == front.
在这里插入图片描述

由此可推断出:在容量为N的数组中,存储的元素个数为:(rear-front+N)%N

3.2循环队列的元素的创建

这里定义一个MAX常量用于记录队列中的元素个数,实际上的数组需要MAX个单位的空间.

typedef int QDataType;
typedef struct Queue {QDataType a[MAX+1];int front;int rear;
}Queue;

3.3循环队列的初始化

//队列的初始化
void InitQueue(Queue* q)//含有MAX个元素的队列,开辟MAX+1个单位空间
{q->front = q->rear = 0;
}

3.4取出队头元素

//出队列
QDataType DeQueue(Queue* q)
{assert(!QueueEmpty(q));QDataType ret = q->a[q->front];q->front = (q->front + 1) % (MAX + 1);return ret;
}

3.5向队尾插入元素

//入队列
void EnQueue(Queue* q, QDataType* x)
{assert(!QueueFull(q));q->a[q->rear] = x;q->rear = (q->rear + 1) % (MAX + 1);
}

3.6队列中存储的元素个数

//队列的元素个数
int QueueSize(Queue* q)
{return (q->rear - q->front + MAX + 1) % (MAX + 1);
}

3.7判断队列是否为空

//判断队列是否为空
bool QueueEmpty(Queue* q)
{return q->front == q->rear;
}

3.8判断队列是否为满

bool QueueFull(Queue* q)
{return (q->rear + 1) % (MAX + 1) == q->front;
}

4.链式队列和循环队列的比较

循环队列是事先申请好空间,使用期间无法释放,而链式队列则不存在这个问题.虽然链式队列在空间上会有更多的开销,但是也在可接受范围之内.所以在空间上,链式队列更加灵活.

相关文章:

数据结构--队列与循环队列的实现

数据结构–队列的实现 1.队列的定义 比如有一个人叫做张三,这天他要去医院看病,看病时就需要先挂号,由于他来的比较晚,所以他的号码就比较大,来的比较早的号码就比较小,需要到就诊窗口从小号到大依次排队,前面的小号就诊结束之后,才会轮到大号来,小号每就诊完毕就销毁,每新来…...

数据结构—栈、队列、链表

一、栈 Stack(存取O(1)) 先进后出,进去123,出来321。 基于数组:最后一位为栈尾,用于取操作。 基于链表:第一位为栈尾,用于取操作。 1.1、数组栈 /*** 基于数组实现的顺序栈&#…...

2023年4月到7月工作经历

2023年4 有同事说程序崩溃一起分析得结果 unsigned uNum 2; std::string str "abc" uNum; std::cout << str; 结果是c 。如果uNum 很大的话&#xff0c;就可能崩溃。 unsigned uNum 2; //std::string str "abc" uN…...

嵌入式Linux应用开发-驱动大全-同步与互斥③

嵌入式Linux应用开发-驱动大全-同步与互斥③ 第一章 同步与互斥③1.4 Linux锁的介绍与使用1.4.1 锁的类型1.4.1.1 自旋锁1.4.1.2 睡眠锁 1.4.2 锁的内核函数1.4.2.1 自旋锁1.4.2.2 信号量1.4.2.3 互斥量1.4.2.4 semaphore和 mutex的区别 1.4.3 何时用何种锁1.4.4 内核抢占(pree…...

力扣-383.赎金信

Idea 使用一个hashmap 或者一个int数组存储第二次字符串中每一个字符及其出现的次数 遍历第一个字符串&#xff0c;讲出现的重复字符减1&#xff0c;若该字符次数已经为0&#xff0c;则返回false AC Code class Solution { public:bool canConstruct(string ransomNote, strin…...

计算机网络 第二章物理层

计算机网络第二章知识点速刷 其中重要的是信源和信宿&#xff0c;以及调制解调器在通信模型当中起到的作用。...

uniapp:动态修改页面标题

我们经常遇到这种情况&#xff0c;点击新增按钮&#xff0c;进入一个空白表单页面&#xff0c;点击修改按钮&#xff0c;其实也是进入这个表单页面&#xff0c;只是表单内容已经被数据库的记录反显了&#xff0c;为了区别页面&#xff0c;我们还需要动态设置页面的标题&#xf…...

java学生管理系统

一、项目概述 本学生管理系统旨在提供一个方便的界面&#xff0c;用于学校或机构管理学生信息&#xff0c;包括学生基本信息、课程成绩等。 二、系统架构 系统采用经典的三层架构&#xff0c;包括前端使用JavaSwing&#xff0c;后端采用Java Servlet&#xff0c;数据库使用M…...

Docker和容器化:简介和使用案例

Docker和容器化&#xff1a;简介和使用案例 引言 容器化技术在近年来变得越来越流行&#xff0c;为开发人员和运维团队提供了更加灵活、高效的软件部署和管理方式。其中&#xff0c;Docker是最为知名和广泛使用的容器化平台之一。本篇博客文章将介绍Docker和容器化的基本概念…...

(高阶) Redis 7 第18讲 RedLock 分布式锁

🌹 以下分享 RedLock 分布式锁,如有问题请指教。🌹🌹 如你对技术也感兴趣,欢迎交流。🌹🌹🌹 如有对阁下帮助,请👍点赞💖收藏🐱‍🏍分享😀 问题 分布式锁问题从(高阶) Redis 7 第17讲 分布式锁 实战篇_PJ码匠人的博客-CSDN博客 这篇文章来看,…...

嵌入式软件架构基础设施设计方法

大家好&#xff0c;今天分享一篇嵌入式软件架构设计相关的文章。 软件架构这东西&#xff0c;众说纷纭&#xff0c;各有观点。在我看来&#xff0c;软件架构是软件系统的基本结构&#xff0c;包含其组件、组件之间的关系、组件设计与演进的规则&#xff0c;以及体现这些规则的基…...

MySQL进阶_3.性能分析工具的使用

文章目录 第一节、数据库服务器的优化步骤第二节、查看系统性能参数第三节、 慢查询日志第四节、 查看 SQL 执行成本第五节、 分析查询语句&#xff1a;EXPLAIN5.1 基本语法5.2 EXPLAIN各列作用 第一节、数据库服务器的优化步骤 当我们遇到数据库调优问题的时候&#xff0c;可…...

Scala第十三章节

Scala第十三章节 1. 高阶函数介绍 2. 作为值的函数 3. 匿名函数 4. 柯里化 5. 闭包 6. 控制抽象 7. 案例: 计算器 scala总目录 文档资料下载...

Nginx高级 第一部分:扩容

Nginx高级 第一部分&#xff1a;扩容 通过扩容提升整体吞吐量 1.单机垂直扩容&#xff1a;硬件资源增加 云服务资源增加 整机&#xff1a;IBM、浪潮、DELL、HP等 CPU/主板&#xff1a;更新到主流 网卡&#xff1a;10G/40G网卡 磁盘&#xff1a;SAS(SCSI) HDD&#xff08;机械…...

vue项目上线后去除控制台所有console.log打印-配置说明

方式一 npm i babel-plugin-transform-remove-console --save-dev babel.config.js文件中添加 // 然后在babel.config.js中添加判断 const prodPlugin []if (process.env.NODE_ENV production) { // 如果是生产环境&#xff0c;则自动清理掉打印的日志&#xff0c;但保留…...

《XSS-Labs》02. Level 11~20

XSS-Labs 索引Level-11题解 Level-12题解 Level-13题解 Level-14题解 Level-15题解 Level-16题解 Level-17题解 Level-18~20题解 靶场部署在 VMware - Win7。 靶场地址&#xff1a;https://github.com/do0dl3/xss-labs 只要手动注入恶意 JavaScript 脚本成功&#xff0c;就可以…...

Java中处理千万级数据的最佳实践:性能优化指南

在今天的数字化时代&#xff0c;处理大规模数据已经成为许多Java应用程序的核心任务。无论您是构建数据分析工具、实现实时监控系统&#xff0c;还是处理大规模日志文件&#xff0c;性能优化都是确保应用程序能够高效运行的关键因素。本指南将介绍一系列最佳实践&#xff0c;帮…...

LCR 069.山峰数组的峰顶索引

​​题目来源&#xff1a; leetcode题目&#xff0c;网址&#xff1a;LCR 069. 山脉数组的峰顶索引 - 力扣&#xff08;LeetCode&#xff09; 解题思路&#xff1a; 二分查找即可。 解题代码&#xff1a; class Solution {public int peakIndexInMountainArray(int[] arr) {…...

AtCoder Beginner Contest 233 (A-Ex)

A.根据题意模拟即可 B.根据题意模拟即可 C.直接用map 进行dp即可 D.用前缀和进行模拟&#xff0c;用map统计前缀和&#xff0c;每次计算当前前缀和-k的个数就是以当前点为右端点答案。 E - Σ[k0..10^100]floor(X&#xff0f;10^k) (atcoder.jp) &#xff08;1&#xff09;…...

解决caffe中的python环境安装的问题

由于caffe&#xff08;GitHub - BVLC/caffe: Caffe: a fast open framework for deep learning.&#xff09;使用的python版本是2.7&#xff0c;而非python3&#xff0c;所以安装的时候使用命令&#xff1a;sudo apt install python2.7进行安装。 而在安装python的各种包时&am…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...

深入理解 React 样式方案

React 的样式方案较多,在应用开发初期,开发者需要根据项目业务具体情况选择对应样式方案。React 样式方案主要有: 1. 内联样式 2. module css 3. css in js 4. tailwind css 这些方案中,均有各自的优势和缺点。 1. 方案优劣势 1. 内联样式: 简单直观,适合动态样式和…...

react更新页面数据,操作页面,双向数据绑定

// 路由不是组件的直接跳转use client&#xff0c;useEffect&#xff0c;useRouter&#xff0c;需3个结合&#xff0c; use client表示客户端 use client; import { Button,Card, Space,Tag,Table,message,Input } from antd; import { useEffect,useState } from react; impor…...

< 自用文 OS有关 新的JD云主机> 国内 京东云主机 2C4G 60G 5Mb 498/36月 Ubuntu22

攒了这么久&#xff0c;废话一些&#xff1a; 前几周很多事儿&#xff0c;打算回北京&#xff0c;开个清真的德克萨斯烤肉店&#xff0c;写了一篇 &#xff1a; &#xff1c; 自用文 Texas style Smoker &#xff1e; 美式德克萨斯烟熏炉 从设计到实现 &#xff08;第一部分&…...

基于规则的自然语言处理

基于规则的自然语言处理 规则方法形态还原&#xff08;针对英语、德语、法语等&#xff09;中文分词切分歧义分词方法歧义字段消歧方法分词带来的问题 词性标注命名实体分类机器翻译规则方法的问题 规则方法 以规则形式表示语言知识&#xff0c;强调人对语言知识的理性整理&am…...

【知识扫盲】分布式系统架构或分布式服务中的管理面,数据面和业务面

&#x1f9e9; 一、三大“面”的定义与职责&#xff08;以大模型推理平台为例&#xff09; 层级英文名职责关键组件举例数据面Data Plane处理用户请求、模型推理、输入输出数据转换等核心任务模型服务引擎、Tokenizer/Detokenizer、推理加速器&#xff08;TensorRT、ONNX Runt…...