队列的讲解和实现(图解+代码/C语言+循环队列OJ)

news2025/1/20 5:56:07

今天为大家分享的是队列的实现,本文主要介绍单向链表来模拟实现队列,最后给出力扣上一道循队列的OJ实现。

目录

 一、图解队列的结构

二、模拟栈的分步实现

(1)队列的初始化

(2)队尾入队

(3)队头出队

(4)获取队头队尾元素

(5)获取队列中有效元素个数

(6)检测队列是否为空

(7)销毁队列

三、循环链表OJ实现

(1)OJ链接

(2)描述

(3)函数实现

Ⅰ. C语言实现

Ⅱ. C++实现


 一、图解队列的结构

对于队列,我们可以用八个字概括“先入先出,后入后出”。“队列”顾名思义就是像公交车排队的队伍一样,排队的时候,先进入到队伍之中的人先完成排队,后进入到队伍之中的人最后才能出去。

二、模拟栈的分步实现

(1)队列的初始化

通过对队列结构的描述我们可以很容易得出,我们会经常对队列的头尾元素进行操作,因此我们需要用两个指针来分别记录头结点和尾结点的位置。在初始化的时候只需要将两个指针置空即可。

// 链式结构:表示队列 
typedef int QDataType;

typedef struct QListNode
{
	struct QListNode* _next;
	QDataType _data;
}QNode;

// 队列的结构 
typedef struct Queue
{
	QNode* _front;
	QNode* _rear;
}Queue;

// 初始化队列 
void QueueInit(Queue* q)
{
	assert(q);
	q->_front = q->_rear = NULL;
}

(2)队尾入队

队列只能从队尾进入,不然就是“插队”,是不可以的哦。入队不仅需要改变尾指针,同样有可能改变头指针,即当队列为空时就需要将头指针和尾指针都指向新的结点。

// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{
	assert(q);
	QNode* new_node = (QNode*)malloc(sizeof(QNode));
	assert(new_node);
	new_node->_data = data;
	new_node->_next = NULL;
	if (q->_rear == NULL)
		q->_rear = q->_front = new_node;
	else
	{
		q->_rear->_next = new_node;
		q->_rear = q->_rear->_next;
	}
}

(3)队头出队

同样类比于队尾出队,出队只能从队头出,同时两个指针都有可能发生改变。

// 队头出队列 
void QueuePop(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));
	QNode* del_node = q->_front;
	if (q->_front->_next == NULL)
	{
		free(q->_front);
		q->_front = q->_rear = NULL;
	}
	else
	{
		q->_front = q->_front->_next;
		free(del_node);
	}
}

(4)获取队头队尾元素

由于我们本身就记录了头尾结点的位置,因此获取头尾结点的值就很容易了,唯一需要注意的时,当队列为空的时候,就不能调用函数了。

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

// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));
	return q->_rear->_data;
}

(5)获取队列中有效元素个数

主要有两种方式可以记录队列中的有效元素个数,首先是遍历链表然后计数一边,另一个方式就是在队列的结构体中添加一个计数器记录,在每次入队和出队的时候对计数器操作,然后返回计数器的值即可。在此演示遍历链表的方式。

// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{
	assert(q);
	QNode* size = q->_front;
	int len = 0;
	while (size)
	{
		len++;
		size = size->_next;
	}
	return len;
}

(6)检测队列是否为空

为了使检测更加严谨,可以同时检测头指针和尾指针,这样可以防止由于在入队和出队时忘记同时对头尾指针操作导致野指针或空指针等问题。

// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{
	assert(q);
	return q->_front == NULL && q->_rear == NULL;
}

(7)销毁队列

销毁队列时需要注意的就是在释放完所有结点之后需要将头尾指针置空,不然会造成野指针问题。

// 销毁队列 
void QueueDestroy(Queue* q)
{
	assert(q);
	QNode* node = q->_front;
	while (q->_front)
	{
		node = q->_front;
		q->_front = q->_front->_next;
		free(node);
	}
	q->_front = q->_rear = NULL;
}

三、循环链表OJ实现

(1)OJ链接

T622 - 中等难度 - 设计循环队列 - 力扣

(2)描述

(3)函数实现

这里实现的方式是利用循环数组模拟,头尾指针也就成了头尾元素的下标,相比较于普通队列,循环队列长度固定,利用数组实现的时候需要注意移动头尾指针的时候可能发生循环,因此要采用取模运算的方式将下标控制在一定范围之内。

Ⅰ. C语言实现

typedef struct 
{
    int* arr;
    int head, tail, size, capacity;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) 
{
    MyCircularQueue* ret = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    ret->arr = (int*)malloc(sizeof(int) * k);
    ret->head = ret->tail = ret->size = 0;
    ret->capacity = k;
    return ret;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
    if (obj->size == obj->capacity)
            return false;
    obj->arr[obj->tail] = value;
    obj->tail++, obj->size++;;
    obj->tail %= obj->capacity;
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) 
{
    if (obj->size == 0)
            return false;
    obj->head++, obj->size--;
    obj->head %= obj->capacity;
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj) 
{
    if (obj->size == 0)
            return -1;
    return obj->arr[obj->head];
}

int myCircularQueueRear(MyCircularQueue* obj) 
{
    if (obj->size == 0)
        return -1;
    return obj->arr[(obj->tail - 1 + obj->capacity) % obj->capacity];
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{
    return obj->size == 0;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) 
{
    return obj->size == obj->capacity;
}

void myCircularQueueFree(MyCircularQueue* obj) 
{
    free(obj->arr);
}

/**
    bool isFull() 
    {
        return size == capacity;
    }
};
*/

Ⅱ. C++实现

class MyCircularQueue 
{
private:
    int* arr;
    int head, tail, size, capacity;
public:
    MyCircularQueue(int k) 
    {
        arr = new int[k];
        head = tail = size = 0;
        capacity = k;
    }

    bool enQueue(int value) 
    {
        if (size == capacity)
            return false;
        arr[tail] = value;
        tail++, size++;;
        tail %= capacity;
        return true;
    }

    bool deQueue() 
    {
        if (size == 0)
            return false;
        head++, size--;
        head %= capacity;
        return true;
    }

    int Front() 
    {
        if (size == 0)
            return -1;
        return arr[head];
    }

    int Rear() 
    {
        if (size == 0)
            return -1;
        return arr[(tail - 1 + capacity) % capacity];
    }

    bool isEmpty() 
    {
        return size == 0;
    }

    bool isFull() 
    {
        return size == capacity;
    }
};

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

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

相关文章

【自学Python】Python比较运算符is和==区别

Python比较运算符is和区别 Python比较运算符is和区别教程 在 Python 中,比较运算符 is 和 is not 用于比较两个对象是否是同一个对象, 和 ! 用于比较两个 变量 的数据是否相等。 案例 比较数值型 数值型,使用 is 和 效果相同 print(&q…

Word控件Spire.Doc 【Table】教程(5):创建表格并在 Doc 文档中设置其边框

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下,轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具,专注于创建、编辑、转…

ROS2机器人编程简述新书推荐-A Concise Introduction to Robot Programming with ROS2

参考链接:https://github.com/fmrico/book_ros2封面:简介:ROS2机器人编程简明教程使用ROS2进行机器人编程的简明介绍为读者提供了通过编程实现机器人所需的概念和工具。它将使读者具备使用ROS2(ROS的新版本)进行项目所…

RT-Thread系列--内存堆MEMHEAP源码分析

一、目的在上一篇《RT-Thread系列--内存池MEMPOOL源码分析》我们介绍了RT-Thread的内存池MEMPOOL实现细节,包括内存池结构和内存块管理。本篇我们来分析一下RT-Thread的内存堆MEMHEAP的实现原理。内存堆MEMHEAP的特点:按需分配,需要多少内存就…

小伟婚后首次看望丈母娘,大衣哥准备了一大三轮车礼品,太豪横了

伴随着春节的临近,大衣哥的儿子小伟, 又一次迎来自己的高光时刻,他和未婚妻一起携手,步入了神圣的婚姻殿堂,大衣哥也长出一口气。儿子小伟再婚,大衣哥完成了一小半任务,接下来还要生孩子&#x…

【Python基础篇】Python中的七种数据类型

文章目录前导一、数字类型(Number)二、布尔类型(Boolean)三、字符串类型(String)3.1 字符串索引3.2 字符串截取、拼接和复用四、列表类型(List)4.1 in和not in4.2 len()4.3 添加/删除…

Three.js 打造酷炫的三角形

在前一章中,我们通过 BufferGeometry 创建了一个正方形,本节我们利用 BufferGeometry 打造一簇酷炫的三角形,最终的效果如下图所示: 从效果图中可以发现,每一个三角形的位置、大小、颜色都是随机的。 // 共有50个三角…

医疗影像工具LEADTOOLS 入门教程: 检测和提取机读旅行证件 - 控制台 C#

LEADTOOLS 是一个综合工具包的集合,用于将识别、文档、医疗、成像和多媒体技术整合到桌面、服务器、平板电脑、网络和移动解决方案中,是一项企业级文档自动化解决方案,有捕捉,OCR,OMR,表单识别和处理&#…

专注分布式架构 莱商银行的数字化转型实践

本文刊登于《金融电子化》杂志 2022 年 12 月下,作者魏汝浩为莱商银行首席信息官。2021 年 12 月 29 日,中国人民银行印发《金融科技发展规划(2022—2025 年)》(银发〔2021〕335 号),提出新时期…

分享166个ASP源码,总有一款适合您

166个ASP源码下载链接:https://pan.baidu.com/s/19W7FmY9nADL1Rge8e5uqiQ?pwdskhh 提取码:skhh import os import shutil import time from time import sleepimport requests from bs4 import BeautifulSoup from docx import Document from docx.sh…

Shader从入门到放弃(四) —— 绘制闪耀星际

前言 经过3个章节的学习,相信大家对shader编程也逐渐的有了一些感觉,所以这次我们玩个“大”的!。 今天的学习内容是绘制“闪耀星际”,正如歌中唱的那样: 星际闪耀光影,落入你的眼睛,如迷人的…

Dubbo泛化调用

Dubbo泛化调用 1. 场景 场景一:我们要搭建一个统一的测试平台,可以让各个业务方在测试平台中通过输入接口、分组名、方法名以及参数值,在线测试自己发布的 RPC 服务。这时我们就有一个问题要解决,我们搭建统一的测试平台实际上是…

【论文速递】CVPR2022 - 泛化的小样本语义分割

【论文速递】CVPR2022 - 泛化的小样本语义分割 【论文原文】:Generalized Few-shot Semantic Segmentation 获取地址:https://openaccess.thecvf.com/content/CVPR2022/papers/Tian_Generalized_Few-Shot_Semantic_Segmentation_CVPR_2022_paper.pdf博…

【ROS2 入门】Jeston TX1 JetPack_4.6.3环境 ubuntu 18.04 ROS2 安装

大家好,我是虎哥,从今天开始,我将花一段时间,开始将自己从ROS1切换到ROS2,在上一篇中,我们再虚拟机环境中安装了 ROS2 eloquent版本,并完成了初步的验证,但是做为一个偏硬件的博主&a…

nginx禁止外网访问

1、安装 libmaxminddb 库 apt updateapt install libmaxminddb0 libmaxminddb-dev mmdb-bin上面安装的软件包是: libmaxminddb0 libmaxminddb-dev 是MaxMind地理定位数据库mmdb-bin – 二进制。 从命令行调用的程序。 使用此命令手动定位 IP 安装参考 2、下载geoi…

node学习笔记

阶段一 1 初始Node.js javascript 运行环境 1.2 Node.js中的javacript 运行环境 1.3 Node.js环境安装 百度 1.4 node.js 执行javaScript 代码 2 fs文件系统模块 2.1 fs文件系统模块概念 导入文件系统模块: const fs require(fs)fs.readFile() // 1 导入fs文件…

【进阶C语言】通讯录(后期会升级)

文章目录一.基本框架与功能二.头文件的详细内容三.函数的实现1.打印菜单2.初始化通讯录3.添加联系人信息4.打印联系人信息5.查找名字6.删除联系人信息7.查找联系人8.修改联系人信息9.排序联系人(按照名字)四.总结1.test.c2.contact.c3.contact.h一.基本框…

智能电风扇(stm32f103c8t6)(直流电机,热敏传感器)(TIM,ADC)

前言 我的毕业论文的课题 提示:以下是本篇文章正文内容,下面案例可供参考 一、热敏传感器计算温度(ADC采样单通道) #include "stm32f10x.h" // Device header#define T25 298.15 #define B 3…

看完这篇 教你玩转渗透测试靶机vulnhub——MONEYBOX: 1

Vulnhub靶机MONEYBOX: 1渗透测试详解Vulnhub靶机介绍:Vulnhub靶机下载:Vulnhub靶机安装:Vulnhub靶机漏洞详解:①:信息收集:②:FTP匿名登入:③:SSH暴力破解④:…

Java操作Word模板产生全新内容Word

1. spire.doc的jar引用 首先我们需要用到国产word处理工具jar包spire.doc,可以通过maven仓库寻找,然后在pom文件中直接引用。 此处需要注意,我们需要使用的是spire.doc.free(免费版的),切勿使用spire.doc&a…