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

【数据结构】三、栈和队列:6.链队列、双端队列、队列的应用(树的层次遍历、广度优先BFS、先来先服务FCFS)

文章目录

    • 2.链队列
      • 2.1初始化(带头结点)
        • 不带头结点
      • 2.2入队(带头结点)
      • 2.3出队(带头结点)
      • ❗2.4链队列c++实例
    • 3.双端队列
      • 考点:输出序列合法性
        • 双端队列
  • 队列的应用
    • 1.树的层次遍历
    • 2.图的广度优先遍历
    • 3.操作系统 - FCFS
  • 补充:释放内存

2.链队列

链队列的front,rear不能存在data的结构体里面,如果那样,每一个结点都有自己的front和raer。

//单链表的结构
typedef struct LinkNode{	//链式队列结点ElemType data;struct LinkNode *next;
}LinkNode;//链队列,队头,对尾结构
//因为队列只处理队头队尾,所以后面只操作这个结构体
typdef struct{				//链式队列LinkNode *front,*rear;	//队列的队头和队尾指针结点
}LinkQueue;

请添加图片描述

2.1初始化(带头结点)

//初始化队列(带头结点)
void InitQueue(LinkQueue &Q){//初始时 front、rear 都指向头结点Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));Q.front->next=NULL;
}

判空

//判断队列是否为空
bool IsEmpty(LinkQueue Q){if(Q.front==Q.rear)return true;elsereturn false;
}
不带头结点
//初始化队列(不带头结点)
void InitQueue(LinkQueue &Q){//初始时 front、rear 都指向NULLQ.front=NULL;Q.rear=NULL;
}//判断队列是否为空(不带头结点)
bool IsEmpty(LinkQueue Q){if(Q.front==NULL)return true;elsereturn false;
}

2.2入队(带头结点)

将元素x入队:

  1. 创建新结点。
  2. 判断内存是否分配成功。
  3. 将元素x放入结点数据域、新节点next指针置空。
  4. 队尾rear指向新结点、更新队尾结点。
//新元素入队(带头结点)
void EnQueue(LinkQueue &Q, ElemType x){LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));if(!s){    //创建结点,分配内存要判断是否分配成功return false; //内存分配失败}s->data=x;s->next=NULL;Q.rear->next=s;//新结点插入到rear之后Q.rear=s;//修改队尾指针
}

2.3出队(带头结点)

步骤:

  1. 判断链队列是否为空。
  2. 创建temp指针指向要出栈的元素。
  3. 用x返回该元素。
  4. 删除该结点:将头结点指向删除结点的后继结点,更新队头。
  5. 若删除的是队尾,则队头队尾指针均指向队头结点。
//队头元素出队(不带头结点)
bool DeQueue(LinkQueue &Q, ElemType &x){ if(Q.front==0.rear)return false;		//空队LinkNode *temp = Q.front->next;x=temp->data;			//用变量x返回队头元素Q.front->next=p->next;	//修改头结点的 next 指针if (Q.rear==temp)		//此次是最后一个结点出队Q.rear=Q.front;		//修改 rear 指针free(temp);				//释放结点空间return true;
}

❗2.4链队列c++实例

#include<iostream>
using namespace std;#define MaxSize 50 //最大队列长度
typedef int QElemType;// 链队列(带头结点)
// C++//结点结构
typedef struct LinkNode
{QElemType data;struct LinkNode* next; 
}LinkNode; //队列结点类型//链队列,队头,对尾结构
//因为队列只处理队头、队尾,所以后面只操作这个结构体
typedef struct
{LinkNode  *front; //队头指针LinkNode  *rear;  //队尾指针
}LinkQueue; //链式队列定义bool InitQueue(LinkQueue& Q);	//循环队列初始化
bool QueueEmpty(LinkQueue Q);	//判断队列是否为空
int  QueueLength(LinkQueue Q);	//循环队列长度bool EnQueue(LinkQueue& Q, QElemType value);	//循环队列入队
bool DeQueue(LinkQueue& Q, QElemType& value);	//循环队列出队QElemType GetHead(LinkQueue Q);		//获取队头元素
bool QueuePrint(LinkQueue Q);		//打印输出队列
void DestroyQueue(LinkQueue& Q); 	//销毁链队列int main()
{LinkQueue Q;QElemType value;InitQueue(Q);int number = 0;		//入队的元素个数cout << "请输入要入队的元素个数:" << " ";cin >> number; int num = 0;		//入队的数据元素while ((number--) > 0){EnQueue(Q, num); //将num入队num++;}cout << "队列输出顺序:";QueuePrint(Q); //遍历输出队列元素cout << "队头元素为:" << GetHead(Q) << endl;cout << "队列长度为:" << QueueLength(Q) << endl;DeQueue(Q, value); //出队cout << "出队元素为:" <<value<<endl;QueuePrint(Q); //遍历队列元素DestroyQueue(Q);//销毁链式队列,释放内存空间return 0;
}//初始化链队列:front与rear都指向队头结点,队头结点next指针置空
bool InitQueue(LinkQueue& Q) {// 将队列的头尾指针都指向同一个节点,表示队列为空Q.front = Q.rear = new LinkNode;  //Q.front = Q.rear = (LinkNode *)malloc(sizeof(LinkNode));if(!Q.front){return false; //内存分配失败}// 带头结点Q.front->next = NULL; //将队列队头指针置空return true; //初始化完成
}//链队列判空
bool QueueEmpty(LinkQueue Q) {//队头队尾指针指向同一位置(队头结点),队列为空。return Q.front == Q.rear;
}//入队
// 将元素value入队:创建新结点,将元素放入结点数据域、新节点next指针置空、队尾rear指向新结点、更新队尾结点。
bool EnQueue(LinkQueue& Q, QElemType value) {// step1创建指针型LinkNode结点,指针指向要插入的结点元素LinkNode* temp = new LinkNode; // step2判断是否分配成功if (!temp) return false; 	//内存分配失败// step3构建新结点temp->data = value;    //将要插入的元素放入temp结点数据域temp->next = NULL;     //temp结点指针域置空// step4将新结点temp插入到队尾Q.rear->next = temp;   //将队尾指针接上temp结点Q.rear = temp;         //更新队尾结点return true; 
}//出队:删除队头结点的下一位,头结点不存储数据元素。
// 判断链队列是否为空,创建temp指针指向要出栈的元素、删除该结点,将头结点指向删除结点的后继结点,更新队头,若删除的是队尾,则队头队尾指针均指向队头结点。
bool DeQueue(LinkQueue& Q, QElemType &value) {// step1判断链队列是否为空if (!QueueEmpty(Q))   //若链队列不为空{// step2创建temp指针指向要出栈的元素LinkNode* temp = Q.front->next;//temp指向队头结点下一位即第一位元素if (!temp)  return false;// step3删除该结点,将头结点指向删除结点的后继结点,更新队头value = temp->data;		//将temp所指结点的数据保存到value中Q.front->next = temp->next;//更新队头结点// step4若删除的是队尾,则队头队尾指针均指向队头结点if (Q.rear == temp)//如果删除的是最后一个结点(尾结点),尾结点回移{Q.rear = Q.front;//rear、front均指向仅存的头结点Q.front->next = NULL;}// step5释放出元素所占结点空间delete temp;  //释放出栈元素所占结点空间return true;  //出栈成功}return false; //队列为空
}//获取链队的队头元素
QElemType GetHead(LinkQueue Q) {if (!QueueEmpty(Q)){return Q.front->next->data;}return false; 
}//链队列的长度/元素个数
// 这里Q不能用'&'引用型传递,否则下方队头指针front的移动会修改原队列front指针。不加引用,就会创建一个副本执行操作,故相比前者会多消耗些内存和时间。也可以创建一个临时指针temp对队列进行遍历,这样即使Q加了&, 也不会影响原链队列。
int QueueLength(LinkQueue Q) {if (!QueueEmpty(Q)){int count = 0;	     //元素个数/队列长度while (Q.front != Q.rear)//直到 == 队尾rear{Q.front = Q.front->next;//队头指针后移一位count++; //计数加一}return count; }return false; //队列为空或不存在
}//遍历输出链队元素
bool QueuePrint(LinkQueue Q)  {if (!QueueEmpty(Q)){while (Q.front != Q.rear){Q.front = Q.front->next;	  //将链队头指针指向第一个元素结点cout << Q.front->data <<" ";  //输出该结点所指的结点数据}cout << endl;return true; }cout << "队列为空或不存在!";return false;  
}//链队列销毁:从队头结点开始,一次释放所有结点
void DestroyQueue(LinkQueue& Q) {LinkNode* temp;   //创建临时指针while (Q.front){ //反正rear指针闲置无事,此处可以不额外创建temp,直接将下列temp替换成Q.rear效果一样。temp = Q.front->next; //temp指向队头结点的下一个结点delete Q.front;  //释放队头结点Q.front = temp;  //更新队头结点}Q.rear = NULL;cout << "队列销毁成功!" << endl;
}

请输入要入队的元素个数: 5
队列输出顺序:0 1 2 3 4
队头元素为:0
队列长度为:5
出队元素为:0
1 2 3 4
队列销毁成功!
Press any key to continue . . .

3.双端队列

按照输出种类从少到多:

队列:只允许从一端插入、另一端删除的线性表。

:只允许从一端插入和删除的线性表。

输入受限的双端队列:只允许从一端插入、两端删除的线性表。
输出受限的双端队列:只允许从两端插入、一端删除的线性表。

双端队列:允许从两端插入、两端删除的线性表。

考点:输出序列合法性

若数据元素输入序列为1,2,3,4。则共有 A 4 4 ! = 24 A^4_4! =24 A44!=24种顺序。

卡特兰(Catalan)数:n个不同元素进栈,出栈元素不同排列的个数为
1 n + 1 C 2 n n \frac 1{n+1}C_{2n}^n n+11C2nn
所以有
1 4 + 1 C 8 4 = 1 5 ∗ 8 ∗ 7 ∗ 6 ∗ 5 4 ∗ 3 ∗ 2 ∗ 1 = 14 \frac 1{4+1}C_{8}^4=\frac1{5}*\frac{8*7*6*5}{4*3*2*1}=14 4+11C84=5143218765=14
种出栈可能。

双端队列

栈中合法的序列,双端队列中一定也合法。

输入受限的双端队列、输出受限的双端队列同样包含栈合法的序列

队列的应用

1.树的层次遍历

在“树”章节会详细学习。

请添加图片描述

2.图的广度优先遍历

在“图”章节会详细学习。

3.操作系统 - FCFS

多个进程争抢着使用有限的系统资源时,FCFS(First Come First Service,先来先服务)是一种常用策略。

eg.: CPU的资源分配。

补充:释放内存

在C语言中,动态分配内存用 malloc() 函数,释放内存用 free() 函数。如下所示:

  1. int *p = (int*) malloc( sizeof(int) * 10 ); //分配10个int型的内存空间
  2. free(p); //释放内存

在C++中,这两个函数仍然可以使用,但是C++又新增了两个关键字,new 和 delete:new 用来动态分配内存,delete 用来释放内存。

用 new 和 delete 分配内存更加简单:

  1. int *p = new int; //分配1个int型的内存空间
  2. delete p; //释放内存

new 操作符会根据后面的数据类型来推断所需空间的大小。

如果希望分配一组连续的数据,可以使用 new[]:

  1. int *p = new int[10]; //分配10个int型的内存空间
  2. delete[] p;

用 new[] 分配的内存需要用 delete[] 释放,它们是一一对应的。

和 malloc() 一样,new 也是在堆区分配内存,必须手动释放,否则只能等到程序运行结束由操作系统回收。为了避免内存泄露,通常 new 和 delete、new[] 和 delete[] 操作符应该成对出现,并且不要和C语言中 malloc()、free() 一起混用。

在C++中,建议使用 new 和 delete 来管理内存,它们可以使用C++的一些新特性,最明显的是可以自动调用构造函数和析构函数。

相关文章:

【数据结构】三、栈和队列:6.链队列、双端队列、队列的应用(树的层次遍历、广度优先BFS、先来先服务FCFS)

文章目录 2.链队列2.1初始化&#xff08;带头结点&#xff09;不带头结点 2.2入队&#xff08;带头结点&#xff09;2.3出队&#xff08;带头结点&#xff09;❗2.4链队列c实例 3.双端队列考点:输出序列合法性栈双端队列 队列的应用1.树的层次遍历2.图的广度优先遍历3.操作系统…...

技术速递|使用 Native Library Interop 为 .NET MAUI 创建绑定

作者&#xff1a;Rachel Kang 排版&#xff1a;Alan Wang 在当今的应用开发领域&#xff0c;通过利用本机功能来扩展 .NET 应用程序的能力非常宝贵。.NET MAUI 处理程序架构使开发人员能够使用 .NET 代码直接操作本机控件&#xff0c;甚至允许无缝创建跨平台自定义控件。然而&a…...

Linux笔记 --- 标准IO

系统IO的最大特点一个是更具通用性&#xff0c;不管是普通文件、管道文件、设备节点文件、接字文件等等都可以使用&#xff0c;另一个是他的简约性&#xff0c;对文件内数据的读写在任何情况下都是带任何格式的&#xff0c;而且数据的读写也都没有经过任何缓冲处理&#xff0c;…...

洛谷:B3625 迷宫寻路

迷宫寻路 题目描述 机器猫被困在一个矩形迷宫里。 迷宫可以视为一个 n m n\times m nm 矩阵&#xff0c;每个位置要么是空地&#xff0c;要么是墙。机器猫只能从一个空地走到其上、下、左、右的空地。 机器猫初始时位于 ( 1 , 1 ) (1, 1) (1,1) 的位置&#xff0c;问能否…...

【C#】explicit、implicit与operator

字面解释 explicit&#xff1a;清楚明白的;易于理解的;(说话)清晰的&#xff0c;明确的;直言的;坦率的;直截了当的;不隐晦的;不含糊的。 implicit&#xff1a;含蓄的;不直接言明的;成为一部分的;内含的;完全的;无疑问的。 operator&#xff1a;操作人员;技工;电话员;接线员;…...

Vue:Vuex-Store使用指南

一、简介 1.1Vuex 是什么 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension (opens new window)&#xf…...

对经典动态规划问题【爬台阶】的一些思考

背景 今天在做Leetcode题目时&#xff0c;做到了一道经典的动态规划问题&#xff1a;爬楼梯&#xff0c;题目的大致意思很简单&#xff0c;有个小孩正在上楼梯&#xff0c;楼梯有n阶台阶&#xff0c;小孩一次可以上1阶、2阶或3阶。实现一种方法&#xff0c;计算小孩有多少种上…...

开发一个能打造虚拟带货直播间的工具!

在当今数字化时代&#xff0c;直播带货已成为电商领域的一股强劲力量&#xff0c;其直观、互动性强的特点极大地提升了消费者的购物体验。 然而&#xff0c;随着技术的不断进步&#xff0c;传统直播带货模式正逐步向更加智能化、虚拟化的方向演进&#xff0c;本文将深入探讨如…...

汽车补光照明实验太阳光模拟器光源

汽车补光照明实验概览 汽车补光照明实验是汽车照明领域的一个重要环节&#xff0c;它涉及到汽车照明系统的性能测试和优化。实验的目的在于确保汽车在各种光照条件下都能提供良好的照明效果&#xff0c;以提高行车安全。实验内容通常包括但不限于灯光的亮度、色温、均匀性、响应…...

MediaPipe人体姿态、手指关键点检测

MediaPipe人体姿态、手指关键点检测 文章目录 MediaPipe人体姿态、手指关键点检测前言一、手指关键点检测二、姿态检测三、3D物体案例检测案例 前言 Mediapipe是google的一个开源项目&#xff0c;用于构建机器学习管道。   提供了16个预训练模型的案例&#xff1a;人脸检测、…...

树上dp之换根dp

基本概念&#xff1a; 换根dp是树上dp的一种 我们在什么时候需要用到换根dp呢&#xff1f; 当题目询问的属性&#xff0c;是需要当前结点为根时的属性&#xff0c;这个时候&#xff0c;我们就要使用换根dp 换根dp的基本思路&#xff1a; 假设题目询问的的属性为x 通常我们…...

2024/8/13 英语每日一段

Mackey says while Whole Foods has become more homogenized under Amazon, it did enable the store to do what it couldn’t have done independently. “People saw us as too expensive and out of touch with our customers,” he says. “The main thing Whole Foods n…...

Java多线程练习(1)

MultiProcessingExercise package MultiProcessingExercise120240813;public class MultiProcessingExercise {public static void main(String[] args) {/*需求&#xff1a;一共有1000张电影票,可以在两个窗口领取,假设每次领取的时间为3000毫秒,请用多线程模拟卖票过程并打印…...

AI高级肖像动画神器LivePortrait

文章目录 前言一、安装1.1 源码安装1.2 windows一键启动包 二、人像生成2.1 浏览器2.2 输入图像2.3 选择驱动视频2.4 生成2.5 结果 三、动物生成3.1 浏览器3.2 输入图片3.3 选择视频3.4 生成3.5 最终结果 四、软件获取 前言 最近&#xff0c;快手可灵大模型团队、中国科学技术…...

Java反射机制深度解析与实践应用

Java反射机制深度解析与实践应用 引言 Java反射是Java语言提供的一种能力&#xff0c;允许程序在运行时访问、检测和修改其自身的属性和行为。反射机制是Java面向对象编程的一大亮点&#xff0c;也是Java框架和库常用的技术之一。 反射的基本概念 反射的核心是java.lang.re…...

Oracle递归查询层级及路径

一、建表及插入数据 ocation_idlocation_nameparent_location_id1广东省NULL2广州市13深圳市14天河区25番禺区26南山区37宝安区3 建表sql&#xff1a; CREATE TABLE locations (location_id NUMBER PRIMARY KEY,location_name VARCHAR2(100),parent_location_id NUMBER ); I…...

leetcode300. 最长递增子序列,动态规划附状态转移方程

leetcode300. 最长递增子序列 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1,6,2,2…...

C语言:字符串函数strcpy

该函数用于字符串的拷贝。 使用方法如下&#xff1a; #include<stdio.h> #include<string.h>int main() {char str[10];char* str1 "abcd";//strcpy(str, str1);//把str1复制到str&#xff0c;但此函数不安全所以用strcpy_sstrcpy_s(str, 10, str1);/…...

Day16-指针2

数组指针与指针数组 变量指针&#xff1a;指向变量的地址。 数组指针&#xff1a;指向数组的地址。 指针变量&#xff1a;存放其他变量地址的变量。 指针数组&#xff1a;存放数组元素指针的变量。 数组指针 概念&#xff1a;数组指针是指向数组的指针。特点&#xff1a; 先…...

数据结构(5.5_3)——并查集的进一步优化

Find操作的优化(压缩路径) 压缩路径——Find操作&#xff0c;先找到根节点&#xff0c;再将查找路径上所有结点都挂到根结点下 代码&#xff1a; //Find "查"操作优化&#xff0c;先找到根节点&#xff0c;再进行"路径压缩" int Find(int S[], int x) {…...

从SEED-Labs实验到实战:手把手教你编写无零字节的x86 Shellcode(附完整代码)

从SEED-Labs实验到实战&#xff1a;手把手教你编写无零字节的x86 Shellcode&#xff08;附完整代码&#xff09; 当你第一次看到"Shellcode"这个词时&#xff0c;可能会联想到某种神秘的编程黑魔法。实际上&#xff0c;它是安全研究中最具实用价值的技能之一——一段…...

Mermaid 可视化工具:提升开发效率的图表编辑解决方案

Mermaid 可视化工具&#xff1a;提升开发效率的图表编辑解决方案 【免费下载链接】vscode-mermaid-preview Previews Mermaid diagrams 项目地址: https://gitcode.com/gh_mirrors/vs/vscode-mermaid-preview 在软件开发过程中&#xff0c;技术文档的编写往往需要插入各…...

保姆级教程:用facenet-pytorch 0.3.0搭建人脸识别环境,CPU/GPU版本一键配置(附避坑清单)

从零构建facenet-pytorch人脸识别环境&#xff1a;CPU/GPU双版本全流程指南 第一次接触人脸识别项目时&#xff0c;最令人头疼的往往不是算法本身&#xff0c;而是环境配置这个"拦路虎"。不同硬件、不同CUDA版本、不同依赖库之间的兼容性问题&#xff0c;足以让新手…...

OpenClaw技能扩展指南:为Phi-3-mini-128k-instruct添加Markdown转换能力

OpenClaw技能扩展指南&#xff1a;为Phi-3-mini-128k-instruct添加Markdown转换能力 1. 为什么需要文档处理技能&#xff1f; 上周我整理技术文档时遇到了一个典型问题&#xff1a;收到同事发来的PDF技术白皮书&#xff0c;需要提取关键章节并转换为Markdown格式存档。手动操…...

Vue项目发版后用户总看到旧页面?3种缓存清理方案实测(含Vue2/Vue3对比)

Vue项目发版后用户总看到旧页面&#xff1f;3种缓存清理方案实测&#xff08;含Vue2/Vue3对比&#xff09; 每次发版后&#xff0c;总有用户反馈"页面没变化"&#xff0c;这可能是浏览器缓存在作祟。作为前端开发者&#xff0c;我们常遇到这类问题——明明服务端已更…...

大数据领域数据预处理:优化数据分析结果的关键环节

大数据领域数据预处理:优化数据分析结果的关键环节 关键词:大数据、数据预处理、数据分析、优化、关键环节 摘要:本文深入探讨了大数据领域中数据预处理这一优化数据分析结果的关键环节。详细介绍了数据预处理的背景知识,包括目的、范围、预期读者等。通过生动形象的比喻解…...

从零部署RT-DETR:手把手教你训练自定义目标检测数据集

1. RT-DETR简介与环境配置 RT-DETR是百度推出的实时目标检测Transformer模型&#xff0c;相比传统CNN架构的YOLO系列&#xff0c;它在保持高精度的同时实现了更快的推理速度。我第一次接触这个模型时&#xff0c;就被它的"端到端检测"特性吸引了——不需要复杂的后处…...

QMCFLAC2MP3深度解析:从格式解密到跨设备音频转换的全流程实践

QMCFLAC2MP3深度解析&#xff1a;从格式解密到跨设备音频转换的全流程实践 【免费下载链接】qmcflac2mp3 直接将qmcflac文件转换成mp3文件&#xff0c;突破QQ音乐的格式限制 项目地址: https://gitcode.com/gh_mirrors/qm/qmcflac2mp3 问题引入&#xff1a;破解音乐格式…...

3步打造智能家居音乐自由:给爱好者的开源方案详解

3步打造智能家居音乐自由&#xff1a;给爱好者的开源方案详解 【免费下载链接】xiaomusic 使用小爱音箱播放音乐&#xff0c;音乐使用 yt-dlp 下载。 项目地址: https://gitcode.com/GitHub_Trending/xia/xiaomusic 在智能家居的日常使用中&#xff0c;许多用户都面临着…...

基于凌科芯安加密芯片智能门锁解决方案

随着物联网产业的快速发展&#xff0c;智能网络设备对信息安全的需求与依赖日益增强。在万物互联的背景下&#xff0c;电子锁作为典型的安全防范产品&#xff0c;在重点场所安防与居民居家安全保障中发挥着关键作用。其中&#xff0c;智能门锁凭借密码、指纹、人脸识别、手机远…...