【数据结构】保姆级队列各接口功能实现

news2024/9/27 7:22:46

目录

🍊前言🍊:

🥝一、队列概述🥝:

1.队列的概念:

2.队列的结构:

🍉二、队列的各接口功能实现🍉:

1.初始化队列:

2.入队(尾插):

3.出队(头删):

4.查看队头:

5.查看队尾:

6.查看队列大小:

7.查看队列容量:

8.队列的销毁:

🍇三、所有接口完整代码🍇:

1.Queue.h:

2.Queue.c:

3.test.c:

🍒总结🍒:


🛰️博客主页:✈️銮同学的干货分享基地

🛰️欢迎关注:👍点赞🙌收藏✍️留言

🛰️系列专栏:🎈 数据结构

                       🎈【进阶】C语言学习

                       🎈  C语言学习

🛰️代码仓库:🎉数据结构仓库

                       🎉VS2022_C语言仓库

        家人们更新不易,你们的👍点赞👍和⭐关注⭐真的对我真重要,各位路过的友友麻烦多多点赞关注,欢迎你们的私信提问,感谢你们的转发!

        关注我,关注我,关注我,你们将会看到更多的优质内容!!


🏡🏡 本文重点 🏡🏡:

🚅 队列概述 🚃 队列各接口功能实现 🚏🚏

🍊前言🍊:

        在上节课中我们使用链表实现了数组栈各接口功能的实现,对各个接口的原理和工作方式由了一定的了解,而今天,在这节课中我们将继续使用链表来实现队列的相关接口功能

🥝一、队列概述🥝:

1.队列的概念:

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

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

2.队列的结构:

🍉二、队列的各接口功能实现🍉:

        队列的实现可以通过数组实现,也可以通过链表来实现,但我们说一般情况下使用链表进行实现会更好

1.初始化队列:

  • 执行操作前需进行非空判断,防止对空指针进行操作。 
  • 判断传入指针非空后,只需将头指针与尾指针置空即可。
void QInit(Q* p)
{
	if (p == NULL)
	{
		printf("QueueINit fail\n");
		return;
	}
	p->head = NULL;
	p->tail = NULL;
}

2.入队(尾插):

  • 执行操作前需进行非空判断,防止对空指针进行操作。 
  • 判断非空后动态申请新节点,并向新结点中存入数据,数据存入后开始插入
  • 节点插入时应当分为两种情况进行讨论,一种是在队列为空,即内部无有效数据时,此时只需使头指针与尾指针均指向新节点,使新节点成为队列中唯一有效数据即可。
  • 另一种情况即为队列中存在着其他有效数据时,此时首先使原本的尾部的 next 指针指向新节点,接着应当更新尾指针,使新节点在连接后真正成为队列的新尾
void QPush(Q* p, QDataType x)
{
	if (p == NULL)
	{
		printf("QueuePush fail\n");
		exit;
	}
	//申请新节点:
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	newnode->data = x;
	newnode->next = NULL;
	//分情况插入:
	if (p->head == NULL)
	{
		p->head = p->tail = newnode;
	}
	else
	{
		//将新节点连接在队尾:
		p->tail->next = newnode;
		//更新队尾:
		p->tail = newnode;
	}
}

3.出队(头删):

  • 执行操作前需进行非空判断,防止对空指针进行操作。
  • 在真正出队操作前,应当对队列内容量进行判断防止对没有有效数据的空队列进行错误操作
  • 判断满足出队条件后,保存头节点中储存的第二节点,接着释放头节点,再使第二节点成为新的头节点即可。
  • 并且同时注意对操作后将队列删空的情况进行区别处理
void QPop(Q* p)
{
	if (p == NULL)
	{
		printf("QueuePop fail\n");
		exit;
	}
	if (QEMpty(p))
	{
		printf("Queue is NUll\n");
		return;
	}
	else
	{
		QNode* next = p->head->next;    //记录第二数据
		free(p->head);    //释放原头节点
		p->head = next;    //更新头节点
		//注意对删空队列的情况应进行区分处理
		if (p->head == NULL)
		{
			p->tail = NULL;
		}
	}
}

4.查看队头:

  • 执行操作前需进行非空判断,防止对空指针进行处理。
  • 这一部分不需要进行什么处理,直接由指针找到队头数据并返回即可。
QDataType QFront(Q* p)
{
	if (p == NULL)
	{
		printf("QueueFront get fail\n");
		return;
	}
    if (QEmpty(p))
	{
		printf("The Queue is NULl\n");
		return;
	}
	return p->head->data;
}

5.查看队尾:

  • 执行操作前需进行非空判断,防止对空指针进行操作。
  • 与队头数据查看相同,无需操作,直接由指针找到并返回队尾数据即可。
QDataType QBack(Q* p)
{
	if (p == NULL)
	{
		printf("QueueBack get fail\n");
		return;
	}
    if (QEmpty(p))
	{
		printf("The Queue is NULl\n");
		return;
	}
	return p->tail->data;
}

6.查看队列大小:

  • 执行操作前需进行非空判断,防止对空指针进行操作。
  • 定义计数变量 count ,遍历整个链式结构(整个队列),数据不为空则计数变量加一,最终返回计数变量的值即可。
int QSize(Q* p)
{
	if (p == NULL)
	{
		printf("QueueSize get fail\n");
		return;
	}
	int count = 0;
	QNode* cur = p->head;
	while (cur)
	{
		++count;
		cur = cur->next;
	}
	return count;
}

7.查看队列容量:

  • 执行操作前应当进行非空判断,防止对空指针进行操作。
  • 处理方式十分简单,直接返回队列是否为空的判断结果即可。
bool QEmpty(Q* p)
{
	if (p == NULL)
	{
		printf("QEmpty fail\n");
		return;
	}
	return p->head == NULL;
}

8.队列的销毁:

  • 执行操作前需进行非空判断,防止对空指针进行操作。
  • 接着由头指针开始,依次遍历释放所有节点,最后再将头指针与尾指针均置空即可。
void QDestroy(Q* p)
{
	if (p == NULL)
	{
		printf("QueueNodeDestroy fail\n");
		exit;
	}
	QNode* cur = p->head;
	while (cur != NULL)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	p->head = p->tail = NULL;
}

🍇三、所有接口完整代码🍇:

1.Queue.h:

#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int QDataType;

typedef struct QueueNode
{
	QDataType data;
	struct QNode* next;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
}Q;

void QInit(Q* p);    //初始化队列
void QPush(Q* p, QDataType x);    //入队
void QPop(Q* p);    //出队
QDataType QFront(Q* p);    //查看队头
QDataType QBack(Q* p);    //查看队尾
int QSize(Q* p);    //查看队列大小
bool QEmpty(Q* p);    //查看队列容量
void QDestroy(Q* p);    //队列的销毁

2.Queue.c:

#define _CRT_SECURE_NO_WARNINGS 1

#include"Queue.h"

//初始化队列
void QInit(Q* p)
{
	if (p == NULL)
	{
		printf("QueueINit fail\n");
		return;
	}
	p->head = NULL;
	p->tail = NULL;
}

//入队:
void QPush(Q* p, QDataType x)
{
	if (p == NULL)
	{
		printf("QueuePush fail\n");
		return;
	}
	//申请新节点:
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	newnode->data = x;
	newnode->next = NULL;
	//分情况插入:
	if (p->head == NULL)
	{
		p->head = p->tail = newnode;
	}
	else
	{
		//将新节点连接在队尾:
		p->tail->next = newnode;
		//更新队尾:
		p->tail = newnode;
	}
}

//出队:
void QPop(Q* p)
{
	if (p == NULL)
	{
		printf("QueuePop fail\n");
		exit;
	}
	if (QEMpty(p))
	{
		printf("Queue is NUll\n");
		return;
	}
	else
	{
		QNode* next = p->head->next;    //记录第二数据
		free(p->head);    //释放原头节点
		p->head = next;    //更新头节点
		//注意对删空队列的情况应进行区分处理
		if (p->head == NULL)
		{
			p->tail = NULL;
		}
	}
}

//查看队头
QDataType QFront(Q* p)
{
	if (p == NULL)
	{
		printf("QueueFront get fail\n");
		return;
	}
	if (QEmpty(p))
	{
		printf("The Queue is NULl\n");
		return;
	}
	return p->head->data;
}

//查看队尾
QDataType QBack(Q* p)
{
	if (p == NULL)
	{
		printf("QueueBack get fail\n");
		return;
	}
	if (QEmpty(p))
	{
		printf("The Queue is NULl\n");
		return;
	}
	return p->tail->data;
}

//查看队列大小
int QSize(Q* p)
{
	if (p == NULL)
	{
		printf("QueueSize get fail\n");
		return;
	}
	int count = 0;
	QNode* cur = p->head;
	while (cur)
	{
		++count;
		cur = cur->next;
	}
	return count;
}

//查看队列容量
bool QEmpty(Q* p)
{
	if (p == NULL)
	{
		printf("QueueEmpty fail\n");
		return;
	}
	return p->head == NULL;
}

//队列的销毁:
void QDestroy(Q* p)
{
	if (p == NULL)
	{
		printf("QueueNodeDestroy fail\n");
		exit;
	}
	QNode* cur = p->head;
	while (cur != NULL)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	p->head = p->tail = NULL;
}

3.test.c:

#define _CRT_SECURE_NO_WARNINGS 1

#include"Queue.h"

void QueueTest()
{
	Q q;
	//初始化队列:
	QInit(&q);
	//入队:
	QPush(&q, 1);
	QPush(&q, 2);
	QPush(&q, 3);
	QPush(&q, 4);
	//出队:
	QPop(&q);
	QPop(&q);
	QPop(&q);
	printf("%d\n", QFront(&q));    //查看队头
	printf("%d\n", QBack(&q));    //查看队尾
	printf("%d\n", QSize(&q));    //查看队列大小
	printf("%d\n", QEmpty(&q));    //查看队列容量
	QDestroy(&q);    //销毁队列
}

int main()
{
	QueueTest();

	return 0;
}

🍒总结🍒:

        至此我们关于队列的各接口功能实现就全部结束了,我们关于栈和队列的接口功能实现均是在链表的基础上完成的,目的在于带领各位小伙伴们熟悉链表的基础结构和逻辑使用,希望各位小伙伴们下去以后能够多加练习,巩固基础,务必掌握链表的相关知识,为以后的 C++ 学习奠定坚实的基础

        🔥🔥没人会嘲笑竭尽全力的人🔥🔥

        更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~  你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

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

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

相关文章

k8s之挂载NFS到POD中

写在前面 在k8s之挂载本地磁盘到POD中 一文中我们看了如何将POD中的数据写到本地磁盘中&#xff0c;这种方式要求POD只能在指定的Node上&#xff0c;一旦POD更换Node&#xff0c;数据依然会丢失&#xff0c;所以本文看下如何通过将数据写到NFS中来解决这个问题。下面我们就开始…

sklearn数据降维之字典学习

文章目录字典学习简介构造函数实战Step1 制作实验数据Step2 小批字典学习Step 3 参数调整字典学习简介 如果把降维理解成压缩的话&#xff0c;那么字典学习的本质是编码&#xff0c;其目的是找到少量的原子&#xff0c;用以描述或构建原始样本。举个一维的例子&#xff0c;以a…

程序员护眼指南

前言 前言&#xff1a;脱发和近视是当代年轻人的两大痛点&#xff0c;今天来聊聊如何护眼。 文章目录前言一、护眼的核心二、调节睫状肌的方法1. 眨眼2. 望远3. 睡觉4. 促进血液循环5. 吃补剂6. 好的屏幕一、护眼的核心 护眼的核心就是保护睫状肌。 睫状肌是眼内的一种平滑肌…

一起自学SLAM算法:7.7 典型SLAM算法

连载文章&#xff0c;长期更新&#xff0c;欢迎关注&#xff1a; 针对式&#xff08;7-38&#xff09;所述的在线SLAM系统&#xff0c;以扩展卡尔曼滤波&#xff08;EKF&#xff09;为代表的滤波方法&#xff0c;是求解该状态估计问题最典型的方法&#xff0c;在7.4节中已经详细…

GY-US42超声波传感器模块介绍

GY-US42超声波传感器模块简介GY-US42 是一款低成本高品质测距传感器模块。工作电压 3-5v&#xff0c;功耗小&#xff0c;体积小&#xff0c;安装方便。其工作原理是&#xff0c;探头发射超声波&#xff0c;照射到被测物体后&#xff0c;探头接收返回声波&#xff0c;利用时间差…

学人工智能电脑主机八大件配置选择指南

来源&#xff1a;深度之眼 作者&#xff1a;frank 编辑&#xff1a;学姐 本篇主要是帮助大家构建高性能、高性价比的AI开发的硬件平台。如何不把钱浪费到不必要的硬件上&#xff0c;并合理搭配硬件配置节省预算是本文想要去讨论的问题。如果预算充足&#xff0c;笔者建议购买一…

【JavaSE专栏1】Java的介绍、特点和历史

作者主页&#xff1a;Designer 小郑 作者简介&#xff1a;Java全栈软件工程师一枚&#xff0c;来自浙江宁波&#xff0c;负责开发管理公司OA项目&#xff0c;专注软件前后端开发&#xff08;Vue、SpringBoot和微信小程序&#xff09;、系统定制、远程技术指导。CSDN学院、蓝桥云…

Python ·保险理赔分析:数据分析

介绍 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 在本笔记本中&#xff0c;我们将仔细研究保险索赔&#xff0c;并弄清一些有关血压、BMI、糖尿病、吸烟、年龄和性别等条件如何影响索赔价值的事实。 我们将使用散点图、饼图、直…

IDEA必装插件-Gyro

前言用SpringBootTest运行单测的时候&#xff0c;是不是每运行都需要重新启动Spring容器&#xff1f;大型应用启动一次会浪费大量的时间&#xff0c;导致效率比较低。Gyro插件可以解决你的问题。Gyro介绍它是一个IDEA插件&#xff0c;安装之后&#xff0c;用Gyro Debug运行你的…

一起自学SLAM算法:7.4 基于贝叶斯网络的状态估计

连载文章&#xff0c;长期更新&#xff0c;欢迎关注&#xff1a; 在7.2.4节中&#xff0c;讨论了表示机器人观测与运动之间依赖关系的概率图模型&#xff0c;主要是贝叶斯网络&#xff08;实际应用在机器人中的是动态贝叶斯网络&#xff09;和马尔可夫网络&#xff08;实际应用…

fpga实操训练(lcd字符显示)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 用fpga编写屏幕显示,和c语言编写有很大的不同。用c语言开发,很大程度上是遵循soc ip提供的规范进行编写。而用fpga开发的话,则需要考虑不同信号的时序关系。但是,用fpga开发也有…

c++ 优先级队列priority_queue的使用

c priority_queue是对其他容器元素顺序的调整包装; 堆的原理 1.定义 priority_queue<Type, Container, Functional> q; 其中&#xff0c;Type是数据类型&#xff0c;Container是低层容器&#xff0c;如vector, stack, deque等. Functional是比较函数&#xff1b;默认可…

day25-类加载器反射

1.类加载器 1.1类加载器【理解】 作用 负责将.class文件&#xff08;存储的物理文件&#xff09;加载在到内存中 1.2类加载的过程【理解】 类加载时机 创建类的实例&#xff08;对象&#xff09;调用类的类方法访问类或者接口的类变量&#xff0c;或者为该类变量赋值使用反…

NodeJS 之 HTTP 模块(实现一个基本的 HTTP 服务器)

NodeJS 之 HTTP 模块&#xff08;实现一个基本的 HTTP 服务器&#xff09;参考描述HTTP 模块搭建 HTTP 服务器http.createServer()监听检测服务器端口是否被占用终端Error Code超时处理处理客户端的请求request 事件http.IncomingMessagehttp.ServerResponse中文乱码问题问题解…

Java EE之线程编(进阶版)

这些锁策略能适用于很多中语言&#xff0c;博主是学Java的&#xff0c;所以下面的代码会用Java去写&#xff0c;请大家见谅&#xff0c;但是处理的方法是大差不差的。 一、常见锁和锁策略&#xff1a; (一)、乐观锁和悲观锁 1、何为乐观锁和悲观锁呢&#xff1f; 答&#…

Linux服务器常见运维性能测试(3)CPU测试super_pi、sysbench

Linux服务器常见运维性能测试&#xff08;3&#xff09;CPU测试常见性能测试软件CPU测试&#xff1a;super_pi &#xff08;计算圆周率&#xff09;CPU测试&#xff1a;sysbench&#xff08;CPU功能测试部分&#xff09;下载安装sysbench综合测试功能执行CPU测试最近需要测试一…

Java面试题含答案,最新面试题(1)

Java 中 InvokeDynamic指令是干什么的&#xff1f; JVM字节码指令集一直比较稳定&#xff0c;一直到Java7中才增加了一个InvokeDynamic 指令&#xff0c;这是JAVA为了实现『动态类型语言』支持而做的一种改进&#xff1b;但是在Java7中并没有提供直接生成InvokeDynamic 指令的…

自定义类型:结构体,枚举,联合

目录一、结构体内存对齐二、位段2.1 什么是位段2.2 位段内存分配规则2.3 位段的跨平台问题三、枚举四、联合体4.1 联合类型的定义4.2联合的特点4.3 联合大小的计算4.4 练习一、结构体内存对齐 struct s {char c1;int i;char c2; }; int main() {printf("%d\n", size…

【Hadoop】HDFS体系结构分析

文章目录1. NameNode2. Secondary NameNode3. DataNodeHDFS主要包含NameNode、Secondary NameNode和DataNode三部分&#xff0c;且这三部分在分布式文件系统中分属不同的机器&#xff0c;其中Secondary NameNode不是必须的&#xff0c;在HA架构中Standby NameNode可以替代它。 …

【深度学习】详解 SimCLR

目录 摘要 一、引言 二、方法 2.1 The Contrastive Learning Framework 2.2. Training with Large Batch Size 2.3. Evaluation Protocol 三、用于对比表示学习的数据增广 3.1 Composition of data augmentation operations is crucial for learning good representa…