队列——“数据结构与算法”

news2024/11/16 15:22:03

各位CSDN的uu们你们好呀,又好久不见啦,最近有点摆烂,甚是惭愧!!!!今天,小雅兰的内容是队列,下面,让我们进入队列的世界吧!!!


队列


队列的概念及结构

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

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

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

 如果:

入队列:1 2 3 4  那么,出队列:1 2 3 4

 DFS——深度优先遍历——递归/栈实现非递归

 BFS——广度优先遍历——队列


几个题目:

1.循环队列的存储空间为 Q(1:100) ,初始状态为 front=rear=100 。经过一系列正常的入队与退队操作后, front=rear=99 ,则循环队列中的元素个数为( D )

A 1

B 2

C 99

D 0或者100

2.以下( B )不是队列的基本运算?

A 从队尾插入一个新元素

B 从队列中删除第i个元素

C 判断一个队列是否为空

D 读取队头元素的值

3.现有一循环队列,其队头指针为front,队尾指针为rear;循环队列长度为N。其队内有效长度为?(假设队头不存放数据) ( B )

A (rear - front + N) % N + 1

B (rear - front + N) % N

C (rear - front) % (N + 1)

D (rear - front + N) % (N - 1)


队列的实现 

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

 定义两个结构体,一个表示队列的结点的结构,一个表示队列的结构

typedef int QDataType;
// 链式结构:表示队列 
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QueueNode;
// 队列的结构 
typedef struct Queue
{
	QueueNode* phead;//头指针
	QueueNode* ptail;//尾指针
	int size;
}Queue;

初始化队列:

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

销毁队列:

一个结点一个结点的释放

// 销毁队列 
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QueueNode* cur = pq->phead;
	while (cur != NULL)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

队尾入队列:

// 队尾入队列 
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;
	//是空队列的情况
	if (pq->ptail == NULL)
	{
		assert(pq->phead == NULL);
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}

检测队列是否为空:

// 检测队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL && pq->ptail == NULL;
}

队头出队列:

// 队头出队列 
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	//1.一个结点
	//2.多个结点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		//相当于头删
		QueueNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	pq->size--;
}

获取队列头部元素:

// 获取队列头部元素 
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->phead->data;
}

 获取队列尾部元素:

// 获取队列队尾元素 
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->ptail->data;
}

获取队列中有效元素的个数:

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

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。


队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。

顺序队列
建立顺序队列结构必须为其静态分配或动态申请一片连续的存储空间,并设置两个指针进行管理。一个是队头指针front,它指向队头元素;另一个是队尾指针rear,它指向下一个入队元素的存储位置,每次在队尾插入一个元素是,rear增1;每次在队头删除一个元素时,front增1。随着插入和删除操作的进行,队列元素的个数不断变化,队列所占的存储空间也在为队列结构所分配的连续空间中移动。当front=rear时,队列中没有任何元素,称为空队列。当rear增加到指向分配的连续空间之外时,队列无法再插入新元素,但这时往往还有大量可用空间未被占用,这些空间是已经出队的队列元素曾经占用过得存储单元。

顺序队列中的溢出现象:
(1) "下溢"现象:当队列为空时,做出队运算产生的溢出现象。“下溢”是正常现象,常用作程序控制转移的条件。
(2)"真上溢"现象:当队列满时,做进栈运算产生空间溢出的现象。“真上溢”是一种出错状态,应设法避免。
(3)"假上溢"现象:由于入队和出队操作中,头尾指针只增加不减小,致使被删元素的空间永远无法重新利用。当队列中实际的元素个数远远小于向量空间的规模时,也可能由于尾指针已超越向量空间的上界而不能做入队操作。该现象称为"假上溢"现象。

循环队列
在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进:无论插入或删除,一旦rear指针增1或front指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置。自己真从MaxSize-1增1变到0,可用取余运算rear%MaxSize和front%MaxSize来实现。这实际上是把队列空间想象成一个环形空间,环形空间中的存储单元循环使用,用这种方法管理的队列也就称为循环队列。除了一些简单应用之外,真正实用的队列是循环队列。

在循环队列中,当队列为空时,有front=rear,而当所有队列空间全占满时,也有front=rear。为了区别这两种情况,规定循环队列最多只能有MaxSize-1个队列元素,当循环队列中只剩下一个空存储单元时,队列就已经满了。因此,队列判空的条件时front=rear,而队列判满的条件时front=(rear+1)%MaxSize。


测试一下队列的功能:

#include"Queue.h"
int main()
{
	Queue p;
	QueueInit(&p);
	QueuePush(&p, 1);
	QueuePush(&p, 2);
	printf("队头元素:%d\n", QueueFront(&p));
	QueuePop(&p);
	QueuePush(&p, 3);
	QueuePush(&p, 4);
	printf("队列中元素个数:%d\n", QueueSize(&p));
	while (!QueueEmpty(&p))
	{
		printf("队头元素:%d\n", QueueFront(&p));
		QueuePop(&p);
	}
	QueueDestroy(&p);
	return 0;
}


源代码如下:

Queue.h的内容:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int QDataType;
// 链式结构:表示队列 
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QueueNode;
// 队列的结构 
typedef struct Queue
{
	QueueNode* phead;//头指针
	QueueNode* ptail;//尾指针
	int size;
}Queue;
// 初始化队列
void QueueInit(Queue* pq);

// 销毁队列 
void QueueDestroy(Queue* pq);

// 队尾入队列 
void QueuePush(Queue* pq, QDataType x);

// 队头出队列 
void QueuePop(Queue* pq);

// 获取队列头部元素 
QDataType QueueFront(Queue* pq);

// 获取队列队尾元素 
QDataType QueueBack(Queue* pq);

// 获取队列中有效元素个数 
int QueueSize(Queue* pq);

// 检测队列是否为空
bool QueueEmpty(Queue* pq);

Queue.c的内容:

#include"Queue.h"
// 初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
// 销毁队列 
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QueueNode* cur = pq->phead;
	while (cur != NULL)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
// 队尾入队列 
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;
	//是空队列的情况
	if (pq->ptail == NULL)
	{
		assert(pq->phead == NULL);
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
// 检测队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL && pq->ptail == NULL;
}
// 队头出队列 
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	//1.一个结点
	//2.多个结点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		//相当于头删
		QueueNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	pq->size--;
}
// 获取队列头部元素 
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->phead->data;
}

// 获取队列队尾元素 
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->ptail->data;
}

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

好啦,小雅兰今天的队列的学习内容就到这里啦,还要继续加油噢!!!

 

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

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

相关文章

Trigger +Pipeline 完整实战案例

2.4.1 案例环境说明 示例项目&#xff1a;http://code.icloud2native.com/root/spring-boot-helloWorld.git 触发机制: 用户推送代码至项目仓库由Push Hook 自东触发pipeline的流水线的执行 2.4.2 项目实现 1、在k8s上部署一个gitlab&#xff0c;前面上节已经完成。 2、运…

海睿思分享 | 类chatgpt模型在信息抽取领域的应用

大语言模型&#xff08;LLM&#xff0c;Large Language Model&#xff09;是指能够处理海量数据、拥有百亿级参数的深度学习模型&#xff0c;它已成为⼈⼯智能领域中的新热点。2022 年 11 ⽉ 30 号 ChatGPT 发布&#xff0c;其卓越的性能表现给整个⾏业带来了巨⼤的冲击。⼈们不…

2023年春季期末网球理论复习资料

&#xff08;含2023/2022/2021时事题&#xff0c;基于2012年期末网球理论复习资料修改&#xff09; 目录 网球的起源 网球的主要赛事 三大网球协会 大满贯 网球的场地 1. 球场线 2. 网球的球网 3.场地的类型 网球的规则 1.发球规则 2.计分方法 3.通则 4.赛…

在Octane中提升渲染速度的技巧(第1部分)

Mike Griggs是一位数字内容创建者&#xff0c;在为众多客户创建Mograph&#xff0c;VFX和CGI方面拥有超过二十年的经验。迈克格里格斯&#xff08;Mike Griggs&#xff09;在Creative Bloq上写了很多博客&#xff0c;该博客是国际媒体集团和领先的数字出版商Future plc的一部分…

手势识别q

本文介绍使用光电传感器的手势识别。 光电传感器手势识别区别于视觉手势识别&#xff0c;没有复杂的算法。LED发射光&#xff0c;当光线接触到手发生反射&#xff0c;反射光被传感器检测到&#xff0c;传感器检测到不同的手势反射的光不同&#xff0c;再根据芯片的内置算法判别…

【笔试强训编程题】Day5.( 统计回文 45842 ) 和( 连续最大和 58539)

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训编程题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;! 文章目录…

【嵌入式烧录/刷写文件】-2.5-Fill填充Intel Hex文件

案例背景(共8页精讲)&#xff1a;该篇将告诉你&#xff0c;如何对一个Hex文件进行填充&#xff1a; 对“起始地址”和“结束地址”内的非连续的Block块&#xff0c;进行填充&#xff1b;自定义填充范围。 目录 1 为什么要“Fill填充” 2 使用Vector HexView工具“填充”Hex…

【Linux0.11代码分析】09 之 ELF可执行程序02 - Section Headers解析

【Linux0.11代码分析】09 之 ELF可执行程序02 - Section Headers解析 一、ELF概述二、ELF的组成结构2.1 ELF header&#xff1a;解析出 section headers 含31个section节和 program headers 含13个segment段2.2 Section Headers&#xff1a;获取当前程序的31个section节区信息2…

18-03 MySQL高可用方案与选择

主从复制 读写分离 流程 原理 bin log STATEMENT 优点&#xff1a;记录的是执行的SQL,比较省空间&#xff0c;降低了主从复制时的IO开销缺点&#xff1a;由于记录的是SQL&#xff0c;所以MySQL多个节点之间复制的时候&#xff0c;特定场景下会导致数据不一致的情况 ROW 优点…

【多线程进阶二】JUC工具类 线程安全的集合类 死锁

目录 一、JUC工具类 &#x1f345;1、Callable接口 &#x1f345;2、ReentrantLock &#x1f345;3、原子类 &#x1f345;4、Semaphore信号量 &#x1f345;5、CountDownLatch 二、线程安全的集合类 ​&#x1f345;1、多线程环境下&#xff0c;怎么使用线程安全…

第十三届蓝桥杯国赛JavaB组题解

A. 重合次数 思路&#xff1a; 枚举不同的时刻&#xff0c;判断哪些时刻秒针和分针表示的数字是相同的。这道题坑就坑在:xx:59:59 xx:00:00分针和时。也就是说一个小时会重叠两次。 题目要求是分钟和秒钟的重叠次数,故时钟,分钟,秒钟同时重叠的次数不算(这题还是有点咬文嚼字了…

MySQL---事务

1. 事务操作 开启事务&#xff1a;Start Transaction 任何一条DML语句(insert、update、delete)执行&#xff0c; 标志事务的开启命令&#xff1a;BEGIN 或 START TRANSACTION 提交事务&#xff1a;Commit Transaction 成功的结束&#xff0c;将所有的DML语句操作历史记录…

G2O学习使用

g2o全称是General Graph Optimization&#xff0c;也就是图优化&#xff0c;我们在做SLAM后端或者更加常见的任何优化问题&#xff08;曲线拟合&#xff09;都可以使用G2O进行处理。 就经验而言&#xff0c;solvers给人的感觉是大同小异&#xff0c;而 types 的选取&#xff0…

C语言小游戏——扫雷

前言 结合前边我们所学的C语言知识&#xff0c;本期我们将使用C语言实现一个简单的小游戏——扫雷 目录 前言 总体框架设计 多文件分装程序 各功能模块化实现 初始化棋盘 棋盘打印 埋雷 判赢与排雷 游戏逻辑安排 总结 总体框架设计 和三子棋相同&#xff0c;游戏开始时…

32岁测试工程师,陷入中年危机,最终我裸辞了....

前言 今年32岁&#xff0c;我从公司离职了&#xff0c;是裸辞。 前段时间&#xff0c;我有一件事情一直憋在心里很难受&#xff0c;想了很久也没找到合适的人倾诉&#xff0c;就借着今天写出来。 我一个十几年IT经验&#xff0c;七年测试经验的职场老人&#xff0c;我慢慢涨…

02 Android开机启动之BootLoader及kernel的启动

Android开机启动之BootLoader及kernel的启动 1、booloader的启动流程 第一阶段:硬件初始化,SVC模式,关闭中断,关闭看门狗,初始化栈,进入C代码 第二阶段:cpu/board/中断初始化;初始化内存以及flash,将kernel从flash中拷贝到内存中,执行bootm,启动内核 2、kernel的启…

学习如何将Jenkins与UI测试报告完美整合,事半功倍,轻松获取高薪职位!

目录 引言 &#xff08;一&#xff09;在本地整合出报告 1.在cmd分别安装pytest和allure-pytest 2.进入需要执行的代码所在的路径 3.运行测试报告&#xff0c;代码如下 4.解析此json文件&#xff0c;代码如下&#xff08;新打开cmd进入路径&#xff09; 5.打开此HTML文件…

包管理工具

包 package&#xff0c;代表了一组特定功能的源码集合。 包管理工具 管理包的应用软件&#xff0c;可以对包进行下载安装、更新、删除、上传等操作。 借助包管理工具&#xff0c;可以快速开发项目&#xff0c;提升开发效率。 常用包管理工具 npm&#xff08;nodejs官方内…

百度API实现自动写诗

作者介绍 张琪&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2022级研究生 研究方向&#xff1a;机器视觉与人工智能 电子邮件&#xff1a;3126743452qq.com 王泽宇&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2022级研究生&#xff0…

Spring——Spring_IOC

1.Spring_IOC概念引入 控制反转 2.Spring_IOC代码测试 IOC代码演示 控制反转&#xff1a;就是创建对象的权力交给了容器 1.创建一个接口&#xff0c;定义一个抽象方法 package org.example;public interface Empdao {int addemp(); } 2.创建一个实现类&#xff0c;实现这…