栈和队列(2)

news2024/9/21 11:17:43

目录

🍁一、链表的概念

🍁二、针对本文章给出的几点注意事项:

🍁三、队列的实现

🌕(一)、代码定义

注意:

🌕(二)、初始化

🌕(三)、入队

🌕(四)、出队

🌕(五)、取队头元素

🌕(六)、取队尾元素

🌕(七)、判空

🌕(八)、获取队列元素个数

🌕(九)、销毁

🌕(十)、遍历

🍁、队列实现源代码

🌕(一)、main.c

🌕(二)、Queue.c

🌕(三)、Queue.h


🍁一、链表的概念

①:队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。
②:队列具有 先进先出(简称FIFO (First In First Out))的特点
③:入队列:进行插入操作的一端称为 队尾
       出队列:进行删除操作的一端称为 队头
④:常见使用场景:

🍁二、针对本文章给出的几点注意事项:

(一)、队列使用单向队列即可,因为双向体现不了它的优势,而且双向还会多一个指针域,内存能省一点是一点

(二)、哨兵位(带头)可要可不要,因为哨兵一般解决结构体二级指针,而本次小编会以另外一种方法解决二级指针的问题

(三)、队列可以用数组实现,也可以用链表来实现,但优先选择链表,对于队列,链表的优势远大于数组,因为数组入队很简单,但出队就涉及数据的覆盖,比较麻烦;

(四)、在链表的头部进行出队,尾部进行入队。

(五)、队列实现的具体步骤我会放在代码注释里面,大家请注意一下!因为小编找不到合适的方式,有推荐的小伙伴可以评论区给小编一些建议。

🍁三、队列的实现

🌕(一)、代码定义

之前实现链表的时候我们知道,在不带头且插入第一个数据时会修改结构体指针,此时就需要使用二级指针的参与,从而分类讨论,是情况变得复杂;既然我们不带头,并且这里即需要头指针还需要尾指针,那么我们可以有如下实现:

typedef int QDatatype;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDatatype data;
}QNode;

typedef struct Queue
{
	QNode* head;//头指针,指向首结点
	QNode* tail;//尾指针,指向为结点
	int size;//记录队列长度
}Que;

我们将头指针head和尾指针tail重新封装成一个结构体,这样即使是在插入第一个数据,那么我们修改head指针,相当于修改结构体Queue的成员,所以我们全部情况只需要结构体Queue的一级指针即可;

注意:

截至目前:我们已经接触了三种改变结构体指针head不需要传参数二级指针的方法:

(一)、就是使用带哨兵的head,这样改变的是head的next域,即改变结构体成员;

(二)、使用不带哨兵的head,但最后会返回新head,在函数外面用适当的指针来接收返回值;

(三)、就是上述所示,在不带哨兵的情况,将头指针、尾指针封装成一个结构体,这样改变head或tail时,改变的是该结构体的成员,只需使用该结构体的一级指针即可;

🌕(二)、初始化

//初始化
void Queueinit(Que* ps)
{
	assert(ps);
	ps->head = ps->tail = NULL;
	ps->size = 0;
}

🌕(三)、入队

①:因为我们使用的是链表结构,所以不用考虑增容;

②:但入队的时候要注意第一次入队时的区别,从而分类讨论;

③:入队后元素数量加1;

//入队
void QueuePush(Que* ps, QDatatype x)
{
	assert(ps);
	//创建一个新结点
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc");
		return;
	}
	//因为是在尾结点入队,所以入队之后结点next域要置空
	newnode->data = x;
	newnode->next = NULL;
	//第一次插入是结构体指针之间的赋值,之后才是结构体成员的赋值,所以要分情况
	//记住tail指针始终指向尾结点,所以入队之后要对tail指针重定位
	if (ps->tail == NULL)
	{
		ps->head = ps->tail = newnode;
	}
	else
	{
		ps->tail->next = newnode;
		ps->tail = newnode;
	}
	//入队后元素数量+1
	ps->size++;
}

🌕(四)、出队

出队的时候也要注意几点事项:

①:出队前,一定要检查队列是否为空;

②:因为队列涉及头指针head和尾指针tail,所以当出队列的最后一个元素后,head和tail指针都要指向NULL,所以我们可以分类讨论以防万一;

③:出队后元素数量size减1

//出队
void QueuePop(Que* ps)
{
	assert(ps);
	//检查队列是否为空,若为空则assert函数报错提示
	assert(!QueueEmpty(ps));
	//队列不为空,进行尾删
	//当对列只剩下一个元素时,要注意head和tail指针都要指向NULL,所以为了安全起见,进行分类讨论
	if (ps->head->next == NULL)
	{
		free(ps->head);
		//注意free释放的是该指针指向的空间,而不是释掉该指针
		ps->head = ps->tail = NULL;
	}
	else
	{
		QNode* next = ps->head->next;
		free(ps->head);
		ps->head = next;
	}
	//出队列,元素数量-1
	ps->size--;
}

🌕(五)、取队头元素

操作很简单,只需返回head结点的data域;

但要注意,首先要检查队列是否为空:

//取队头
QDatatype QueueFront(Que* ps)
{
	assert(ps);
	//检查队列为不为空
	assert(!QueueEmpty(ps));
	//返回首结点的data域
	return ps->head->data;
}

🌕(六)、取队尾元素

操作和(五)类似:

//取队尾
QDatatype QueueBack(Que* ps)
{
	assert(ps);
	//检查队列为不为空
	assert(!QueueEmpty(ps));
	//返回尾结点的data域
	return ps->tail->data;
}

🌕(七)、判空

规则:

队列为空返回真;

队列不为空返回假;

我们用一个表达式的逻辑值来实现,如下:

//判空
bool QueueEmpty(Que* ps)
{
	assert(ps);
	//为空返回真,不为空返回假
	return (ps->head == NULL);
}

🌕(八)、获取队列元素个数

操作很简单,直接返回size即可:


//获取队列元素个数
int QueueSize(Que* ps)
{
	assert(ps);
	return ps->size;
}

🌕(九)、销毁

与单链表的销毁类似,一个结点一个结点的销毁;

先用临时指针cur指向head,再用临时指针next保存cur的下一个结点,再释放当前结点cur,然后cur重定位到下一个结点,直至cur为NULL;

//销毁
void QueueDestroy(Que* ps)
{
	assert(ps);
	QNode* cur = ps->head;
	//先保存下一个结点,在释放当前结点,在重定位
	while (cur)
	{
		QNode* Qnext = cur->next;
		free(cur);
		cur = Qnext;
	}
	ps->head = ps->tail = NULL;
	ps->size = 0;
}

🌕(十)、遍历

与栈类似的,队列遍历的时候也不用封装成函数,而是用循环,边遍历边出队,遍历完后,队列为空,这与其后面使用场景有着密切联系;

void Queuetest1()
{
	Que ps;
	Queueinit(&ps);
	QueuePush(&ps, 1);
	QueuePush(&ps, 2);
	QueuePush(&ps, 3);
	QueuePush(&ps, 4);
	QueuePush(&ps, 5);

	//遍历
	while (!QueueEmpty(&ps))
	{
		//当前数据是整形,所以占位符用%d
		printf("%d ", QueueFront(&ps));
		QueuePop(&ps);
	}
	printf("\n");
	QueueDestroy(&ps);
}

先进先出,符合其特征;

🍁、队列实现源代码

🌕(一)、main.c


#include"Queue.h"

void Queuetest1()
{
	Que ps;
	Queueinit(&ps);
	QueuePush(&ps, 1);
	QueuePush(&ps, 2);
	QueuePush(&ps, 3);
	QueuePush(&ps, 4);
	QueuePush(&ps, 5);

	//遍历
	while (!QueueEmpty(&ps))
	{
		//当前数据是整形,所以占位符用%d
		printf("%d ", QueueFront(&ps));
		QueuePop(&ps);
	}
	printf("\n");
	QueueDestroy(&ps);
}


int main()
{
	Queuetest1();
	return 0;
}

🌕(二)、Queue.c

#include"Queue.h"

//初始化
void Queueinit(Que* ps)
{
	assert(ps);
	ps->head = ps->tail = NULL;
	ps->size = 0;
}

//销毁
void QueueDestroy(Que* ps)
{
	assert(ps);
	QNode* cur = ps->head;
	//先保存下一个结点,在释放当前结点,在重定位
	while (cur)
	{
		QNode* Qnext = cur->next;
		free(cur);
		cur = Qnext;
	}
	ps->head = ps->tail = NULL;
	ps->size = 0;
}

//入队
void QueuePush(Que* ps, QDatatype x)
{
	assert(ps);
	//创建一个新结点
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc");
		return;
	}
	//因为是在尾结点入队,所以入队之后结点next域要置空
	newnode->data = x;
	newnode->next = NULL;
	//第一次插入是结构体指针之间的赋值,之后才是结构体成员的赋值,所以要分情况
	//记住tail指针始终指向尾结点,所以入队之后要对tail指针重定位
	if (ps->tail == NULL)
	{
		ps->head = ps->tail = newnode;
	}
	else
	{
		ps->tail->next = newnode;
		ps->tail = newnode;
	}
	//入队后元素数量+1
	ps->size++;
}

//出队
void QueuePop(Que* ps)
{
	assert(ps);
	//检查队列是否为空,若为空则assert函数报错提示
	assert(!QueueEmpty(ps));
	//队列不为空,进行尾删
	//当对列只剩下一个元素时,要注意head和tail指针都要指向NULL,所以为了安全起见,进行分类讨论
	if (ps->head->next == NULL)
	{
		free(ps->head);
		//注意free释放的是该指针指向的空间,而不是释掉该指针
		ps->head = ps->tail = NULL;
	}
	else
	{
		QNode* next = ps->head->next;
		free(ps->head);
		ps->head = next;
	}
	//出队列,元素数量-1
	ps->size--;
}

//取队头
QDatatype QueueFront(Que* ps)
{
	assert(ps);
	//检查队列为不为空
	assert(!QueueEmpty(ps));
	//返回首结点的data域
	return ps->head->data;
}

//取队尾
QDatatype QueueBack(Que* ps)
{
	assert(ps);
	//检查队列为不为空
	assert(!QueueEmpty(ps));
	//返回尾结点的data域
	return ps->tail->data;
}


//判空
bool QueueEmpty(Que* ps)
{
	assert(ps);
	//为空返回真,不为空返回假
	return (ps->head == NULL);
}

//获取队列元素个数
int QueueSize(Que* ps)
{
	assert(ps);
	return ps->size;
}

🌕(三)、Queue.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdbool.h>
#include<stdlib.h>

typedef int QDatatype;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDatatype data;
}QNode;

typedef struct Queue
{
	QNode* head;//头指针,指向首结点
	QNode* tail;//尾指针,指向为结点
	int size;//记录队列长度
}Que;

//初始化
void Queueinit(Que* ps);

//销毁
void QueueDestroy(Que* ps);

//入队
void QueuePush(Que* ps,QDatatype x);

//出队
void QueuePop(Que *ps);

//取队头
QDatatype QueueFront(Que* ps);

//取队尾
QDatatype QueueBack(Que* ps);

//判空
bool QueueEmpty(Que* ps);

//获取队列元素个数
int QueueSize(Que* ps);

本次知识到此结束,希望对你有所帮助

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

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

相关文章

java.java.lang.NoSuchMethodError: org.bouncycastle.math.ec.ECFieldElement

目录 Java运行时异常:行时找不到指定的方法 1.前言2.原因2.1项目中的版本有冲突2.2项目中某个包缺少bouncycastle依赖 总结参考 1.前言 java.lang.NoSuchMethodError: org.bouncycastle.math.ec.ECFieldElement$Fp.(Ljava/math/BigInteger;Ljava/math/BigInteger;) java.lang…

(PC+WAP)照明科技类网站模板 LED灯具照明网站源码下载

(PCWAP)照明科技类网站模板 LED灯具照明网站源码下载 PbootCMS内核开发的网站模板&#xff0c;该模板适用于照明科技网站、灯具照明网站等企业&#xff0c;当然其他行业也可以做&#xff0c;只需要把文字图片换成其他行业的即可&#xff1b; pcwap&#xff0c;同一个后台&#…

【网安大模型专题10.19】论文6:Java漏洞自动修复+数据集 VJBench+大语言模型、APR技术+代码转换方法+LLM和DL-APR模型的挑战与机会

How Effective Are Neural Networks for Fixing Security Vulnerabilities 写在最前面摘要贡献发现 介绍背景&#xff1a;漏洞修复需求和Java漏洞修复方向动机方法贡献 数据集先前的数据集和Java漏洞Benchmark数据集扩展要求数据处理工作最终数据集 VJBenchVJBench 与 Vul4J 的…

SSO 系统设计_token 生成

SSO 系统设计_token 生成 目录概述需求&#xff1a; 设计思路实现思路分析1.增加依赖2.代码编写3.测试 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wai…

IT行业职场走向,哪些方向更有就业前景?——IT行业的发展现状及趋势探析

文章目录 每日一句正能量前言IT技术发展背景及历程IT行业的就业方向有哪些&#xff1f;分享在IT行业的就业经历后记 每日一句正能量 如果你认为你自己无法控制自己的情绪&#xff0c;这就是一种极为严重的不良暗示。 前言 在信息量浩如烟海、星罗棋布的大数据时代&#xff0c;…

深度学习第四阶段:NLP第二章 Transformer学习笔记

引言1&#xff1a;什么是注意力机制 参考我的一篇文章&#xff1a;https://blog.csdn.net/weixin_42110638/article/details/134011134?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22134011134%22%2C%22source%22%3A%22weixin…

优优嗨聚集团:抖音外卖,美食与文化的完美结合

在今天的数字化时代&#xff0c;外卖行业正在迅速发展&#xff0c;而抖音外卖的出现&#xff0c;更是引领了外卖行业的新潮流。抖音外卖不仅满足了人们对美食的追求&#xff0c;还让人们在享受美食的同时&#xff0c;感受到了浓厚的文化氛围。 抖音外卖是抖音平台推出的一项全新…

RISC Zero zkVM性能指标

1. 引言 对应代码&#xff1a; https://github.com/risc0/risc0&#xff08;C和Rust&#xff09; 运行如下指令&#xff0c;进行性能评估&#xff1a; cargo run -r --example loop //CPU cargo run -r -F metal --example loop //Metal GPU cargo run -r -F cuda --exampl…

Seata入门系列【14】AT模式源码分析之二阶段全局提交和全局回滚

1 全局提交 1.1 前言 在之前我们分析了&#xff0c;开启全局事务&#xff0c;和业务执行时是如何校验全局锁和提交本地事务的&#xff0c;接下来分析下是如何进行全局提交的。 1.2 二阶段全局提交 核心代码还是在TransactionalTemplate类中&#xff0c;当TC 没有收到异常时…

2023高频前端面试题-http

1. HTTP有哪些⽅法&#xff1f; HTTP 1.0 标准中&#xff0c;定义了3种请求⽅法&#xff1a;GET、POST、HEAD HTTP 1.1 标准中&#xff0c;新增了请求⽅法&#xff1a;PUT、PATCH、DELETE、OPTIONS、TRACE、CONNECT 2. 各个HTTP方法的具体作用是什么&#xff1f; 方法功能G…

论坛议程|COSCon'23青少年开源与开源教育(E)

众多开源爱好者翘首期盼的开源盛会&#xff1a;第八届中国开源年会&#xff08;COSCon23&#xff09;将于 10月28-29日在四川成都市高新区菁蓉汇举办。本次大会的主题是&#xff1a;“开源&#xff1a;川流不息、山海相映”&#xff01;各位新老朋友们&#xff0c;欢迎到成都&a…

OceanGPT:面向海洋科学的大型语言模型初探

海洋覆盖了约 71% 的地球表面&#xff0c;对全球的气候调节、天气模式、生物多样性以及人类的经济发展都扮演着至关重要的角色。海洋科学专注于研究海洋的自然特性、其变化规律以及与海洋资源开发和利用相关的理论、方法与应用。 本文介绍一个为海洋领域打造的大型语言模型——…

分享一款低损耗 高效率高性能 低 VCE(sat) 晶体管 NSS60600MZ4T1G

关于低 VCE(sat) 晶体管&#xff1f; 是指其饱和电压 VCE(sat) 很低的晶体管。VCE(sat) 是指晶体管在饱和区时&#xff0c;集电极与发射极之间的电压降。低 VCE(sat) 晶体管的优点是在同样的电流下&#xff0c;其 VCE(sat) 更低&#xff0c;因此能够降低电路总成本&#xff0c…

Python的web自动化学习(二)Selenium安装和环境配置

前置条件&#xff1a; 1、安装Python并配置环境变量 2、安装编辑器PyCharm Seleenium安装 正文如下&#xff1a; python常见安装命令&#xff1a; 首先电脑 winR 打开 输入cmd&#xff0c;回车&#xff0c;使用pip安装selenium&#xff1a; 也可以使用命令&#xff1a;…

工作中出现什么「迹象」,表明你应该换工作了?

作者&#xff1a;苍何&#xff0c;CSDN 2023 年 实力新星&#xff0c;前大厂高级 Java 工程师&#xff0c;阿里云专家博主&#xff0c;土木转码&#xff0c;现任部门技术 leader&#xff0c;专注于互联网技术分享&#xff0c;职场经验分享。 &#x1f525;热门文章推荐&#xf…

ITOT强强联合,得帆信息X树根互联打造工业制造融合解决方案

上海得帆信息技术有限公司&#xff08;以下简称“得帆”&#xff09;和树根互联股份有限公司&#xff08;以下简称“树根互联”&#xff09;携手推出了创新性的IT/OT融合产品解决方案&#xff0c;为制造型企业提供了一站式轻量级工业互联网平台。 --- 填补大型制造企业在IT建…

一秒推软文发稿平台:优质客户服务的承诺

在互联网时代&#xff0c;软文发稿已经成为企业推广和营销的重要手段之一。通过发布优质的软文内容&#xff0c;企业可以提升品牌知名度、引流潜在客户、增加销售业绩。然而&#xff0c;对于企业而言&#xff0c;选择一家可靠、专业的软文发稿平台至关重要。在众多的选择中&…

SpringMVC Day02 : 请求方式

前言 欢迎阅读 Spring MVC 系列教程的第二篇文章&#xff01;在上一篇文章中&#xff0c;我们介绍了 Spring MVC 的基本概念和使用方法。今天&#xff0c;我们将深入探讨 Spring MVC 中不同的请求方式&#xff0c;以及如何在你的应用程序中正确地处理它们。 在 Web 开发中&am…

转转闲鱼交易猫三合一后台源码

1、一键添加商品&#xff0c;商品管理&#xff0c;一键分享功能&#xff0c;包括卡框功能 这个样式图就是后台生成完的一个链接截图 后台一键生成&#xff0c;独立后台管理 教程&#xff1a;修改conf数据库账号密码 不会的可以看源码里有搭建教程 下载程序&#xff1a;htt…

基于教与学算法的无人机航迹规划-附代码

基于教与学算法的无人机航迹规划 文章目录 基于教与学算法的无人机航迹规划1.教与学搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用教与学算法来优化无人机航迹规划。 1.教与学…