数据结构-队列

文章目录

    • 队列
      • 队列概述
      • 顺序队
        • 结构体
        • 顺序队基本操作
          • 初始化队列
          • 判断队空
          • 入队操作
          • 出队操作
      • 循环队列
        • 结构体
        • 循环队列基本操作
          • 初始化队列
          • 判断队空
          • 入队操作
          • 出队操作
      • 链队
        • 结构体
        • 链队的基本操作
          • 初始化队列
          • 判断队空
          • 入队操作
          • 出队操作
      • 队列的应用
        • 循环队列双端都可插入删除
        • 循环链表表示队列,只设队尾指针
        • 二叉树层次遍历

队列

队列概述

  • 概述:队列是线性结构的一种,数组组成的队列是顺序队列,链表组成的队列是链队,还有一种特殊的队列概念上首位相邻叫做循环队列。
  • 队列的特点
    • 先进先出、后进后出
    • 队列是在一端进行插入元素,在另一端进行删除元素,插入元素的一端叫做队尾,删除元素的一端叫做队头。尾进头出
  • 队列的应用场景
    • 网络数据传输:在网络传输中,队列可以用来存储待发送的数据包,保证数据的顺序和完整性。
    • 任务调度:在操作系统中,队列可以用来存储待执行的任务,确保任务按照先后顺序执行。
    • 消息队列:在分布式系统中,队列可以用来实现消息的异步传输和处理,提高系统的可伸缩性和可靠性。
    • 事件处理:在事件驱动的系统中,队列可以用来存储待处理的事件,确保事件按照顺序被处理。
    • 缓存管理:在计算机系统中,队列可以用来实现缓存管理,缓解系统压力,提高性能。
    • 批处理:在数据处理系统中,队列可以用来存储待处理的数据,实现批量处理和优化资源利用。
    • 系统监控:在监控系统中,队列可以用来存储待处理的监控数据,确保数据的实时性和完整性。
    • 任务排队:在服务行业中,队列可以用来排队等待服务,确保服务的公平性和顺序性。

顺序队

  • 概述:顺序队,是由数组实现的
结构体
typedef struct SqQueue{int data[maxSize];int front;                               // 队头指针int rear;                                // 队尾指针
}SqQueue;
顺序队基本操作
初始化队列
void initQueue(SqQueue &qu){qu.front = qu.rear = 0;            // 队首和队尾指针重合
}
判断队空
int isEmpty(SqQueue qu){if(qu.front == qu.rear){return 1;						// 头指针等于尾指针,队空}else{return 0;						// 否则队不空}
}

注意:队空返回 1 ,队列不空返回 0。

入队操作
int enQueue(SqQueue &qu , int x){if(qu.rear == maxSize){			// 尾指针等于最大空间,队满return 0;                                        }// 队尾进元素qu.rear += 1;qu.data[qu.rear] = x;           // 存入元素return 1;
}

注意:入队需要判断队满,队满的条件是队尾指针等于数组最大空间数,但是这样,队头出元素会浪费很多时间

出队操作
int deQueue(SqQueue &qu , int &x){if(qu.front == qu.rear){			// 队空,出队失败 return 0;                                }       x = qu.data[qu.front];              // 元素赋值qu.front -= 1;						// 队头指针移动return 1;
}

循环队列

  • 概述:循环队列是由普通队列的演变而来,是因为普通队列在出队操作后,队列的头部空间就无法利用,导致空间的浪费,为了解决这一问题,循环队列产生了,循环队列就是将队列的头尾相连,形成一个环状结构,这样就可以循环利用头部空间避免浪费

  • 循环队列的特点

    // 队空
    front == rear;                              // 头指针和尾指针 相等// 队满
    front = (rear + 1)%maxSize;
    rear = (front -1 + maxSize)%maxSize;// 入队、出队,均先移动指针
    rear = (rear + 1)%maxSize;
    front = (front + 1)%maxSize;
    
结构体
typedef struct Queue{int data[maxSize];int front;                             // 队头指针int rear;                              // 队尾指针
}Queue;
循环队列基本操作
初始化队列
void initQueue(SqQueue &qu){qu.front = qu.rear = 0;            // 队首和队尾指针重合
}
判断队空
int isEmpty(SqQueue qu){if(qu.front == qu.rear){			// 队空return 1;}else{								// 队满return 0;}
}
入队操作
int enQueue(SqQueue &qu , int x){if(qu.front == (qu.rear + 1)%maxSize){return 0;                            // 队满,进队失败}/*队尾进元素,队头出元素*/qu.rear = (qu.rear + 1)%maxSize;         // 移动尾指针,指向空位置qu.data[qu.rear] = x;                    // 存入元素return 1;
}
出队操作
int deQueue(SqQueue &qu , int &x){if(qu.front == qu.rear){return 0;                           // 队空,出队失败 }qu.front = (qu.front + 1)%maxSize;      // 移动头指针,指向出队元素x = qu.data[qu.front];                  // 元素赋值return 1;
}

链队

  • 概述:链队,是由链表实现的
结构体
// 队列结点
typedef struct QNode{int data;struct QNode *next;
}QNode;
// 链队
typedef struct LiQueue{ QNode *front;                            // 队头指针QNode *rear;                             // 队尾指针
}LiQueue;
链队的基本操作
初始化队列
void initQueue(LiQueue *&lqu){lqu = (LiQueue *)malloc(sizeof(LiQueue));lqu->front = lqu->rear = NULL;
}
判断队空
int isEmpty(LiQueue *lqu){if(lqu->front == NULL || lqu->rear == NULL){return 1;}else{return 0;}
}
入队操作
void enQueue(LiQueue *lqu , int x){QNode *p;p = (QNode *)malloc(sizeof(QNode));                   // 创建一个新结点p->data = x;p->next = NULL;/*如果队列为空,则插入结点是首元结点,头、尾指针都指向*/if(lqu->front == NULL || lqu->rear == NULL){lqu->front = p;lqu->rear = p;}else{                            // 新结点链接到队尾即可lqu->rear->next = p;lqu->rear = p;} 
}

注意:单链表入队,无需判断队满

出队操作
int deQueue(LiQueue *lqu , int &x){QNode *p;if(lqu->front == NULL || lqu->rear == NULL){return 0;                                        // 队空不能出队}else{p = lqu->front;                                  // 减少冗余if(lqu->front == lqu->rear){                     // 只剩下首元结点// p = lqu->front;lqu->front = lqu->rear = NULL;               // 指针指向,删除结点}else{// p = lqu->front;lqu->front = p->next;}}x = p->data;free(p);                                              // 释放结点return 1;
}

注意:出队需要判断队空,链队入队和出队要注意 第一个元素的入队最后一个元素的出队

队列的应用

循环队列双端都可插入删除
  • 案例:如果允许在循环队列的两端都可以进行插入和删除操作,完成下述三个需求?
    • 写出循环队列的类型定义
    • 写出从队头删除和队尾插入的算法
    • 写出从队尾删除和队头插入的算法
/* 循环队列的类型定义 */
typedef struct cyQueue{int data[maxSize];                       // maxSize 为已定义的常量int front,rear;
}cyQueue;/* 从队头删除和队尾插入的算法 */
/*队头删除元素*/
int deQueue(cyQueue &cqu , int &x){if(cqu.front == cqu.rear){                 		// 队空return 0;}cqu.front = (cqu.front + 1)%maxSize;       		// 指针移动,移到第一个删除元素x = cqu.data[cqu.front];                  return 1;
}/*队尾进入元素*/
int enQueue(cyQueue &cqu , int x){if(cqu.front == (cqu.rear + 1)%maxSize){		// 队满return 0;}cqu.rear = (cqu.rear + 1)%maxSize;              // 指针移动,移动到空位置插入元素cqu.data[cqu.rear] = x;return 1;
}/* 从队尾删除和队头插入的算法 */
/*队尾删除元素*/
int deQueue(cyQueue &cqu , int &x){if(cqu.front == cqu.rear){						// 队空return 0;}x = cqu.data[cqu.rear];                         // 先赋值cqu.rear = (cqu.rear - 1 + maxSize)%maxSize;	// 尾指针移动return 1;
}/*队头插入元素*/
int enQueue(cyQueue &cqu , int x){if(cqu.rear == (cqu.front -1 + maxSize)%maxSize){return 0;									// 队满}cqu.data[cqu.front] = x;cqu.front = (cqu.front - 1 + maxSize)%maxSize;  // 头指针移动return 1;
}

注意:头插尾山,是逆时针从大到小的顺序

循环链表表示队列,只设队尾指针
  • 案例:假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾结点,但不设头指针,请写出相应的入队列和出队列的算法
  • 代码分析
    • 循环链表有一个尾指针 rear
    • 在循环链表尾部执行元素入队
    • 在循环链表头部执行元素出队
/*入队列*/
void enQueue(LNode *&rear , int x){                 // rear 指针发生改变LNode *s = (LNode *)malloc(sizeof(LNode));s->next = NULL;s->data = x;             						// x 给结点赋值/*头插法,将新结点插入循环链表尾部*/s->next = rear->next;rear->next = s;rear = rear->next;       						// 指针后移
}/*出队列:方式一*/
int deQueue(LNode *&rear , int &x){LNode *p;/*出队列判断队空*/if(rear->next == rear){       					// 只有头结点return 0;}else{p = rear->next->next;if(rear->next->next == rear){				// 只有首元结点,特殊处理rear = rear->next;}else{  									// 不只有首元结点rear->next->next = p->next;}x = p->data;free(p);return 1;}
}/*出队列:方式二*/
int deQueue(LNode *&rear , int &x){LNode *p;if(rear->next == rear){return 0;}else{p = rear->next->next;						// p 指向首元结点rear->next->next = p->next;					// 删除结点x = p->data;if(p == rear)rear = rear->next;free(p);return 1;}
}
二叉树层次遍历
  • 代码分析
    • 层次遍历要用到 队列,在这里我们使用循环队列,定义队列
    • 根结点入队列,然后根节点出队列(并输出访问),然后检查当前结点的左右子树,左非空,左子树先入队列,右非空,右子树再入队列
    • 然后当队列不空的时候一直循环,将队头元素弹出,重复 2)
void level(BTNode *bt){/*定义队列,并初始化*/BTNode *que[maxSize];int front , rear;front = rear = 0;BTNode *p;if(bt != NULL){rear = (rear + 1)%maxSize;que[rear] = bt;while(front != rear){							// 队列不空front = (front + 1)%maxSize;p = que[front];visit(p);									// 访问 pif(p->lChild != NULL){						// 左子书进入队列que[(rear + 1)%maxSize] = p->lChild;}if(p->rChild != NULL){						// 右子树进入队列que[(rear + 1)%maxSize] = p->rChild;}}}
}

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

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

相关文章

SpringBoot的自动装配原理

一、SpringBootConfiguration注解的作用 SpringBootApplication注解是SpringBoot项目的核心注解,加在启动引导类上。点击进去可以发现SpringBootApplication注解是一个组合注解。其中SpringBootConfiguration和EnableAutoConfiguration是由Spring提供的,剩下的注解是由JDK提供的…

简单计算与模拟1:鸡兔同笼(POJ 3237)

1 问题描述 图1 问题描述 2 解题思路 鸡有两只脚&#xff0c;兔子有四只脚&#xff0c;且输入数据可能为奇数&#xff0c;使用公式计算即可。 3 设计代码 #include <cstdio> int main() {int nCases, nFeets;while (scanf("%d", &nCases) ! EOF){for (in…

负载均衡-Ribbon-自定义负载均衡算法

1.Ribbon 是什么 SpringCloud Ribbon 是基于 Netflix Ribbon 实现的一套客户端负载均衡的工具主要功能是提供客户端的软件负载均衡算法&#xff0c;将 Netflix 的中间服务处连接在一起Ribbon的客户端组件提供一系列完整的配置项&#xff0c;如&#xff1a;连接超时、重试等。简…

数据结构——链式栈

采用链式存储的方式来构建栈 #include<bits/stdc.h>using namespace std;#define ElementType inttypedef struct LinkNode{ElementType data;struct LinkNode *next; } *LiStack;bool InitStack(LiStack &S){S (LinkNode *)malloc(sizeof(LinkNode));if(S NULL){…

R语言【taxa】——as_taxon():转换为 taxon 对象

Package taxa version 0.4.2 Description 将其他对象转换为 taxon 向量。taxon 构造器可能将 基础向量转换为 taxon 向量。 Usage as_taxon(x, ...) Arguments 参数【x】&#xff1a;要转换为 taxon 向量的对象。 参数【...】&#xff1a;其余参数。 Examples x <- taxo…

计算机视觉技术综述

目录 一、技术背景 1、什么是计算机视觉技术 2、该技术兴起的背景 二、国内外计算机视觉技术现状 1、计算机视觉技术分类、发展历程及其可能导致社会问题&#xff0c;研究中存在问题&#xff0c;如何改进。 计算机视觉技术分类&#xff1a; 计算机视觉主要发展历程&#xff1a;…

echarts 绘制垂直滚动热力图

问题1&#xff1a;提示功能无效 问题2&#xff1a;值筛选无效 效果 在线浏览 下载echarts官网例子(heatmap Examples - Apache ECharts) 稍作改动&#xff1a; generateData 入参改为长度和宽度noise.perlin2(i / 40, j / 20) Math.random() * 5y轴倒置指定zlevel为2 通过定…

SpringMVC-文件上传与下载

文章目录 文件上传与下载1.下载2.上传 文件上传与下载 1.下载 RequestMapping("/testDown")public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {//获取servletcontext对象ServletContext servletcontextsession.get…

蓝桥杯备战——7.DS18B20温度传感器

1.分析原理图 通过上图我们可以看到DS18B20通过单总线接到了单片机的P14上。 2.查阅DS18B20使用手册 比赛的时候是会提供DS18B20单总线通讯协议的代码&#xff0c;但是没有提供读取温度数据的代码&#xff0c;所以还是需要我们去查看手册&#xff0c;我只把重要部分截下来了 …

将Android APP安装到sm8550 HDK的NVMe SSD

APP存储路径 在Android中&#xff0c;App在运行过程中主要访问的数据路径通常包括以下几个方面&#xff1a; 内部存储&#xff08;Internal Storage&#xff09;&#xff1a;App会访问其私有的内部存储空间&#xff0c;这个空间通常位于&#xff1a; /data/data/<package…

python-自动篇-运维-根据计算机硬盘、主板、CPU生成注册信息

文章目录 准备代码效果 准备 本实例需要使用WMI模块&#xff0c;所以需要安装WMI模块。在安装WMI模块之前&#xff0c;先要安装pywin32模块&#xff0c;WMI模块需要win32api的支持。使用pip安装pywin32模块和WMI模块的代码如下&#xff1a; pip install win32com pip install …

Ubuntu 22.04 安装tomcat

tomcat是常用的Java服务容器,这篇文章我们就来讲讲如何安装它。 更新软件包 首先是更新软件包,这是最常规的操作 sudo apt update 然后是开始安装,不多一会就可以安装好了 sudo apt install tomcat9 然后看一下状态 sudo systemctl status tomcat9 发现虽然启动了,但…

openssl3.2/test/certs - 053 - Name constraints subordinate CA. Adds

文章目录 openssl3.2/test/certs - 053 - Name constraints subordinate CA. Adds概述笔记END openssl3.2/test/certs - 053 - Name constraints subordinate CA. Adds 概述 openssl3.2 - 官方demo学习 - test - certs 笔记 /*! * \file D:\my_dev\my_local_git_prj\study\…

Python第十一章(推导式)

一。列表推导式&#xff1a;目的化简代码&#xff0c;可以改变数据 例句1&#xff1a;如果while循环继续创建序列累加 例句2&#xff1a;如果for循环进行列表累加 1.循环列表推导式进行累加&#xff1a; 注释&#xff1a;第一个i表示的是返回的数据于列表&#xff0c;for后面内…

windows上使用anconda安装tensorrt环境

windows上使用anconda安装tensorrt环境 1 安装tensorrt1.1 下载最新的稳定的tensorrt 8.6.1(tensorrt对应的cuda、cudnn等版本是参考链接4)1.2 将tensorrt添加到环境变量1.3 安装tensorrt依赖1.4 安装Pycuda1.5 安装pytorch 2 测试2.1 测试TensorRT 样例(这个测试主要来源于参考…

【Python】01快速上手爬虫案例一:搞定豆瓣读书

文章目录 前言一、VSCodePython环境搭建二、爬虫案例一1、爬取第一页数据2、爬取所有页数据3、格式化html数据4、导出excel文件 前言 实战是最好的老师&#xff0c;直接案例操作&#xff0c;快速上手。 案例一&#xff0c;爬取数据&#xff0c;最终效果图&#xff1a; 一、VS…

docker生命周期管理命令

文章目录 前言1、docker create2、docker run2.1、常用选项2.2、系统2.3、网络2.4、健康检查 3、docker start/stop/restart4、docker kill5、docker rm6、docker pause/unpause总结 前言 在云原生时代&#xff0c;Docker已成为必不可少的容器管理工具。通过掌握Docker常用的容…

uniCloud发行部署H5进行网页托管

生成文件&#xff0c;生成文件这个和我们平时用uniapp 生成H5的时候是一样的&#xff0c;我们可以选择hash 或者history 模式&#xff0c;默认的这是显示的根目录&#xff0c;如果我们在根目录下建立了H5目录&#xff0c;那么我们在发布H5的时候&#xff0c;是需要在manifest.j…

数据恢复与硬盘修理

目录 第1章 基础知识 1.1 数据恢复技术的发展和研究现状 1.2 数据恢复技术的层次与体系 1&#xff0e;网络层 2&#xff0e;网络存储层 DAS NAS 3&#xff0e;磁盘阵列层 4&#xff0e;磁盘层 5&#xff0e;文件系统层 6&#xff0e;文件层 7&#xff0e;覆盖恢复…

php 源码加密保护 bease方案

推荐使用 php-bease 这个免费开源方案。 有一说一&#xff0c;这个项目上次更新时间是2021年… 多好的项目呀。 作者说在 php5.1 ~ php7.2 上都测试过。 源码地址&#xff1a; C源码&#xff1a; https://github.com/liexusong/php-beast dll版&#xff1a; https://github…