栈和队列详解(2)

news2025/4/24 14:08:57

目录

一、什么是队列?

二、创建一个我们自己的队列

1.前置准备

1.1需要的三个文件

  1.2结构体的创建和头文件的引用

2.接口的实现

2.1初始化队列

2.2入队

2.3队列元素个数和判空

 2.4取队头元素和队尾元素

 2.5出队

 2.6摧毁队列

2.7测试接口

 三、所有代码

1.接口实现

2.队列的头文件

3.测试代码


一、什么是队列?

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。可以形象地将队列想象成生活中的挤地铁,在挤地铁的时候我们只能够从后面进入队伍,出也只能够从队头出到地铁。总结:队列是只支持尾插头删的线性表。 

 二、创建一个我们自己的队列

1.前置准备

1.1需要的三个文件

在开始之前,我们最好创建三个文件,一个放栈函数的实现,一个用来测试栈函数,最后一个放栈函数的引用和头文件的引用,这样到时侯想要使用栈函数直接包这一个头文件即可。创建完之后,呈现出来的效果与下图差不多即可。

  1.2结构体的创建和头文件的引用

由于队列需要头删,使用数组实现的话最终呈现出来的效率十分低下,我们这里使用链表的方式实现,使用链表来实现线性表,头和尾是经常要用到的,同样队列的长度也很重要。因此我们创建两个结构体变量,一个结构体变量为链表的节点,一个结构体变量存放链表的头和尾以及队列的长度。

最终呈现出来的结果是这样的 

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int QueDateType;
//到时修改类型时只用改这里的一个就可以,不需要一个个修改
//同样,这也是为了和单一的int作区分
typedef struct QueueListNode
{
	struct QueueListnode* next;
	//存放下一个节点
	QueDateType data;
	//存放当前节点的数据
}Quenode;
typedef struct QueueInformation
{
	Quenode* head;//存放头节点
	Quenode* tail;//存放尾节点
	int sz;//存放个数
}Que;

2.接口的实现

2.1初始化队列

没什么好说的,将队列的两个指针变为空,存放个数的变量变为0即可

void init_queue(Que* q1)
{
	assert(q1);
    //q1存放的是结构体的指针,不应为空,为空操作不了
	q1->head = NULL;
	q1->tail = NULL;
	q1->sz = 0;
}

2.2入队

void push_queue(Que* q1, QueDateType x)
{
	assert(q1);
	//创建一个新节点,并初始化
	Quenode* newnode = (Quenode*)malloc(sizeof(Quenode));	
	if (newnode == NULL)
	{
		perror("push_queue");
		exit(-1);
	}
	newnode->next = NULL;
	newnode->data = x;
	if (q1->head == NULL)
	//如果头为空,意味着还没有节点,单独处理
	{
		q1->head = q1->tail = newnode;
	}
	else
	{
		q1->tail->next = newnode;
		//原来的尾链接上新的尾
		q1->tail = newnode;
		//将尾更新
	}
	q1->sz++;
}

2.3队列元素个数和判空

可能有小伙伴不明白为什么又要设计这两个接口,因为这两个信息都可以直接通过队列的结构体获得,好像没什么作用啊。设计这两个接口并使用它们而不是直接通过结构体的内容来判断是因为,当我们的需求发生改变了,所创建的结构体可能也会跟着修改,可能提取的方式会发生一些改变   如果我们在使用队列的时候已经直接通过结构体的内容进行了多次的判断,那么我们要修改起来,要修改多次,很不方便,这样做的好处就是只用修改一次即可

队列元素个数

int size_queue(Que* q1)
{
	assert(q1);
	return q1->sz;
}

判空

int empty_queue(Que* q1)
{
	assert(q1);
	return q1->sz == 0;
	//相等即为空,返回1(真)
	//不相等即为非空,返回0(假)
}

 2.4取队头元素和队尾元素

这两个操作很相似,唯一要注意的就是,为空的时候不能取

取队头元素

QueDateType queue_front(Que* q1)
{
	assert(q1);
	assert(!empty_queue(q1));
	//队列不能是空
	return q1->head->data;
}

取队尾元素 


QueDateType queue_back(Que* q1)
{
	assert(q1);
	assert(!empty_queue(q1));
	//队列不能是空
	return q1->tail->data;
}

 2.5出队

需要注意的是,不能够删除空队列,其次我们删除到最后一个节点时要单独处理

void pop_queue(Que* q1)
{
	assert(q1);
	assert(!empty_queue(q1));
	if (q1->head->next == NULL)
	//最后一个节点单独处理
	//避免尾指针变野指针
	{
		free(q1->head);
		q1->head = NULL;
		q1->tail = NULL;
	}
	else
	{
		Quenode* next = q1->head->next;
		free(q1->head);
		q1->head = next;
	}
	q1->sz--;
}

 2.6摧毁队列

void destroy_queue(Que* q1)
{
	assert(q1);
	Quenode* cur = q1->head;
	while (cur)
	{
		Quenode* next = cur->next;
		free(cur);
		cur = next;
	}
}

2.7测试接口

测试代码:

#include"queue.h"
void test1()
{
	Que q1;
	init_queue(&q1);
	push_queue(&q1, 1);
	push_queue(&q1, 2);
	push_queue(&q1, 3);
	push_queue(&q1, 4);
	push_queue(&q1, 5);
	printf("%d\n", queue_back(&q1));
	while (!empty_queue(&q1))
	{
		printf("%d ", queue_front(&q1));
		pop_queue(&q1);
	}
	destroy_queue(&q1);
}
int main()
{
	test1();
}

测试结果:

 三、所有代码

1.接口实现

#include"queue.h"
void init_queue(Que* q1)
{
	assert(q1);
    //q1存放的是结构体的指针,不应为空,为空操作不了
	q1->head = NULL;
	q1->tail = NULL;
	q1->sz = 0;
}
void push_queue(Que* q1, QueDateType x)
{
	assert(q1);
	//创建一个新节点,并初始化
	Quenode* newnode = (Quenode*)malloc(sizeof(Quenode));	
	if (newnode == NULL)
	{
		perror("push_queue");
		exit(-1);
	}
	newnode->next = NULL;
	newnode->data = x;
	if (q1->head == NULL)
	//如果头为空,意味着还没有节点,单独处理
	{
		q1->head = q1->tail = newnode;
	}
	else
	{
		q1->tail->next = newnode;
		//原来的尾链接上新的尾
		q1->tail = newnode;
		//将尾更新
	}
	q1->sz++;
}
int size_queue(Que* q1)
{
	assert(q1);
	return q1->sz;
}
int empty_queue(Que* q1)
{
	assert(q1);
	return q1->sz == 0;
	//相等即为空,返回1(真)
	//不相等即为非空,返回0(假)
}
QueDateType queue_front(Que* q1)
{
	assert(q1);
	assert(!empty_queue(q1));
	//队列不能是空
	return q1->head->data;
}
QueDateType queue_back(Que* q1)
{
	assert(q1);
	assert(!empty_queue(q1));
	//队列不能是空
	return q1->tail->data;
}
void pop_queue(Que* q1)
{
	assert(q1);
	assert(!empty_queue(q1));
	if (q1->head->next == NULL)
	//最后一个节点单独处理
	//避免尾指针变野指针
	{
		free(q1->head);
		q1->head = NULL;
		q1->tail = NULL;
	}
	else
	{
		Quenode* next = q1->head->next;
		free(q1->head);
		q1->head = next;
	}
	q1->sz--;
}
void destroy_queue(Que* q1)
{
	assert(q1);
	Quenode* cur = q1->head;
	while (cur)
	{
		Quenode* next = cur->next;
		free(cur);
		cur = next;
	}
}

2.队列的头文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int QueDateType;
//到时修改类型时只用改这里的一个就可以,不需要一个个修改
//同样,这也是为了和单一的int作区分
typedef struct QueueListNode
{
	struct QueueListnode* next;
	//存放下一个节点
	QueDateType data;
	//存放当前节点的数据
}Quenode;
typedef struct QueueInformation
{
	Quenode* head;//存放头节点
	Quenode* tail;//存放尾节点
	int sz;//存放个数
}Que;
void init_queue(Que* q1);
void push_queue(Que* q1, QueDateType x);
void pop_queue(Que* q1);
int size_queue(Que* q1);
int empty_queue(Que* q1);
QueDateType queue_front(Que* q1);
QueDateType queue_back(Que* q1);
void destroy_queue(Que* q1);

3.测试代码

#include"queue.h"
void test1()
{
	Que q1;
	init_queue(&q1);
	push_queue(&q1, 1);
	push_queue(&q1, 2);
	push_queue(&q1, 3);
	push_queue(&q1, 4);
	push_queue(&q1, 5);
	printf("%d\n", queue_back(&q1));
	while (!empty_queue(&q1))
	{
		printf("%d ", queue_front(&q1));
		pop_queue(&q1);
	}
	destroy_queue(&q1);
}
int main()
{
	test1();
}

好了,今天的分享到这里就结束了感谢各位友友的来访,祝各位友友前程似锦O(∩_∩)O

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

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

相关文章

web应用越用越卡怎么办

简介 如果你的网页应用越用越卡,你就有理由怀疑存在内存泄露 在开发Web应用程序时&#xff0c;经常会遇到内存泄漏的问题&#xff0c;这可能导致应用程序的性能下降或崩溃。Chrome浏览器提供了一个内存面板&#xff0c;可以帮助我们识别并解决这些问题。本文将介绍如何使用Chr…

JavaScript版本ES5/ES6及后续版本

JavaScript简史 1995&#xff1a; Brendan Eich在短短10天内创建了JavaScript的第一个版本。它被称为摩卡&#xff0c;但已经具备了现代JavaScript的许多基本特性! 1996&#xff1a; 为了吸引Java开发人员&#xff0c;Mocha先是更改为LiveScript&#xff0c;然后又更改为Ja…

SSH无法连接kali,拒绝密码

1&#xff0c;cd /etc/ssh 2,systemctl start ssh.server 3,vim /etc/ssh/sshd_config 将黄色文字改成这样 4&#xff0c;systemctl restart ssh 然后去连接就好了

关于达梦网络通信异常问题

一.问题说明 springboot的项目&#xff0c;多数据源&#xff0c;其中一个数据源是达梦数据库。有个根据主键id查询详情的接口&#xff0c;一直报错网络通信异常&#xff0c;或连接尚未建立或者已经关闭。可以确保访问数据库的网络一切正常&#xff0c;单单一张表的接口一直报上…

C# Blazor 学习笔记(12):css样式设置

文章目录 前言添加引入css保证razor和css的对应关系手动引入css文件 前言 由于Blazor UI库暂时还不完善&#xff0c;有时候需要我们自己写css。Razor做好了css动态隔离的设置。 ASP.NET Core Blazor CSS 隔离 C#小轮子&#xff1a;Visual Studio自动编译Sass文件 添加引入c…

回归预测 | MATLAB实现POA-CNN-GRU鹈鹕算法优化卷积门控循环单元多输入单输出回归预测

回归预测 | MATLAB实现POA-CNN-GRU鹈鹕算法优化卷积门控循环单元多输入单输出回归预测 目录 回归预测 | MATLAB实现POA-CNN-GRU鹈鹕算法优化卷积门控循环单元多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现POA-CNN-GRU鹈鹕算法优化卷积门…

使用 Postman 批量发送请求的最佳实践

目录 背景 批量发送&#xff1f; 起因 思考 Postman 批量发送接口 创建集合和接口 批量发送接口 资料获取方法 背景 最近写了几个接口&#xff1a; 获取 books 的接口获取 likes 的接口获取 collections 的接口 但是我还是不放心&#xff0c;因为这些接口到底稳不稳…

智头条|DFM-2大模型吹热智能家居,360安全云正式发布

行业动态 DFM-2大模型吹热智能家居 近期,思必驰行业语言计算大模型DFM-2正式发布,也带来了人机交互能力的提升和优秀的技术落地能力。DFM-2大模型与DUI平台结合推出DUI2.0,完成了对话式AI全链路技术的升级,推进深度产业应用。在智能家居领域,目前思必驰已与海信、长虹美菱、老…

Hadoop Hbase Hive 版本对照一览

这里写目录标题 一、Hadoop 与 Hbase 版本对照二、Hadoop 与 Hive 版本对照 官网内容记录&#xff0c;仅供参考 一、Hadoop 与 Hbase 版本对照 二、Hadoop 与 Hive 版本对照

无涯教程-Perl - mkdir函数

描述 此功能使用MODE指定的模式创建一个名称和路径EXPR的目录,为清楚起见,应将其作为八进制值提供。 语法 以下是此函数的简单语法- mkdir EXPR,MODE返回值 如果失败,此函数返回0,如果成功,则返回1。 例 以下是显示其基本用法的示例代码- #!/usr/bin/perl -w$dirname &…

CKA考试真题(2)-- 绝对干货!

目录 前言 11. NetworkPolicy网络策略 12. Deployment暴露端口/创建Service 13. 创建Ingress 14. 创建pvc及挂载pvc的pod 前言 17道真题难度等级 一级 rbac cpu 扩容 pod指定节点 pv pod日志 排障 查看可用节点 多容器pod 节点维护 二级 networkpolicy service ingress pv…

centos修改DNS方法

如何修复dns服务器&#xff1f;dns服务器由解析器和域名服务器组成&#xff0c;主要存储网络中所有主机的域名和相应的ip地址。关于dns服务器有很多问题&#xff0c;我们将在这里给出一个具体的答案。 1、什么是dns&#xff1f; dns是指&#xff1a;域名服务器&#xff08;域…

Learning Deep Features for Discriminative Localization

Some Words: 这里主要是我阅读paper的笔记 这篇文章主要是2016年CVPR的一篇文章&#xff0c;中文名是 学习用于判别性定位的深度特征&#xff0c; &#xff08;一&#xff09;Abstract: 在这篇工作中&#xff0c;我们又重新探讨了全局平均池化层&#xff0c;并且阐释了CNN网络…

6、CCS 配置工程头文件批量添加路径的方法

1、进入到图示的框框里 2、编辑好需要添加的路径&#xff0c;并按ctrl c 3、选中include paths&#xff08;-I&#xff09;框框里的最后一条路径 4、然后ctrl v&#xff0c;这样路径就复制到预定义路径里了

领航优配:厄尔尼诺现象引发全球粮食危机,印度大米出口禁令引发恐慌性囤货

近期&#xff0c;全球多地遭受厄尔尼诺现象带来的极点气候影响&#xff0c;农业出产遭到严峻搅扰&#xff0c;粮食价格呈现大幅动摇。其中&#xff0c;印度作为全球最大的大米出口国&#xff0c;因为干旱导致大米产值下降&#xff0c;政府宣告制止部分大米出口&#xff0c;引发…

接口测试自动化:简化测试流程,提升效率

接口测试自动化&#xff1a;简化测试流程&#xff0c;提升效率 什么是接口测试自动化&#xff1f; 接口测试自动化是指使用特定的工具和技术来自动化执行接口测试的过程。通过编写脚本&#xff0c;自动化工具可以模拟用户与软件系统的交互&#xff0c;验证接口的功能和性能。…

Java SPI介绍

SPI Java SPI : Service Provider Interface 是Java平台提供的一种机制&#xff0c;用于动态的加载和扩展功能的机制&#xff0c;它为框架和库提供了一种松耦合的扩展方式&#xff0c;核心是解耦。 例如JDBC驱动&#xff0c;日志框架&#xff0c;等应用&#xff0c;它为开发…

【Axure教程】账单列表和详情

账单列表和详情页在支付系统中不仅是用户了解财务状况和跟踪交易的关键工具&#xff0c;还有助于提高支付安全性、解决问题以及满足法律和财务要求。因此&#xff0c;设计一个清晰、易用且功能丰富的账单管理系统对于支付系统的成功运营和用户满意度至关重要。 今天作者就教大…

端点中心(Endpoint Central)的软件许可证管理

软件许可证管理 &#xff08;SLM&#xff09; 是从单个控制台管理整个组织中使用的软件许可证的过程。软件许可证是由软件发行商或分销商制作的法律文件&#xff0c;提供有关软件使用和分发的规则和指南&#xff0c;本文档通常包含条款和条件、限制和免责声明。 软件许可证管理…

原型和原型链理解

这个图大概能概括原型和原型链的关系 1.对象都是通过 _proto_ 访问原型 2.原型都是通过constructor 访问构造函数 3.原型是构造函数的 prototype 4.原型也是对象实例 也是通过 _proto_ 访问原型(Object.prototype) 5.Object.prototype的原型通过 _proto_ 访问 为null 那么…