C语言数据结构之队列

目录

    • 1.队列的概念及结构
    • 2.队列的实现逻辑
    • 3.队列的代码实现
    • 4.相关例题
      • 选择题

在这里插入图片描述
•͈ᴗ•͈ 个人主页:御翮
•͈ᴗ•͈ 个人专栏:C语言数据结构
•͈ᴗ•͈ 欢迎大家关注和订阅!!!

在这里插入图片描述

1.队列的概念及结构

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

与栈不同的是,队列的出栈顺序是先入先出,就像我们出火车站,先排队的人排在前面,就先出站(插队不算奥,队列不可以插队,要做守规则的宝宝)

在这里插入图片描述

2.队列的实现逻辑

和栈一样,队列也可以用顺序表和链表来实现,但是我们要实现出队列,就相当于要实现头删数据的操作,对顺序表来说头删一个数据需要把后面的每一个数据都往前移动,消耗太大了,而对于链表而言只需要操作一个节点,比较简单,所以我们选择使用链表来实现队列

在这里插入图片描述

关于队列,我们要实现以下几个接口:

//初始化队列
void Init_Queue(Queue* ptr);


//打印队列里面的数据
void Print_Queue(Queue* ptr);


//数据入队列
void Push_Queue(Queue* ptr, QDatatype val);


//数据出队列
void Pop_Queue(Queue* ptr);


//获取队头的数据
QDatatype Queue_Front(Queue* ptr);


//获取队尾的数据
QDatatype Queue_Back(Queue* ptr);


//获取队列储存的元素个数
int Queue_Size(Queue* ptr);


//判断队列是否为空
int Check_Empty(Queue* ptr);


//销毁队列
void Destroy_Queue(Queue* ptr);

3.队列的代码实现

test.c

#include "Queue.h"

void menu()
{
	printf("******************************************\n");
	printf("***************   请选择   ***************\n");
	printf("******  1.PushQueue    2.PopQueue   ******\n");
	printf("******  3.Print        4.QueueFront ******\n");
	printf("******  5.QueueBack    6.QueueSize  ******\n");
	printf("******  7.CheckEmpty   0.Exit       ******\n");
	printf("******************************************\n");
}

int main()
{
	int input = 0;
	QDatatype value = 0;
	Queue que;
	Init_Queue(&que);

	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入你要入队的值>:");
			scanf("%d", &value);
			Push_Queue(&que, value);
			break;
		case 2:
			Pop_Queue(&que);
			break;
		case 3:
			Print_Queue(&que);
			break;
		case 4:
			if (que.head == NULL)
			{
				printf("队列为空\n");
				break;
			}
			printf("队列头部元素为%d\n", Queue_Front(&que));
			break;
		case 5:
			if (que.tail == NULL)
			{
				printf("队列为空\n");
				break;
			}
			printf("队列尾部元素为%d\n", Queue_Back(&que));
			break;
		case 6:
			printf("队列中有效元素的个数为%d\n", Queue_Size(&que));
			break;
		case 7:
			if (Check_Empty(&que))
				printf("队列为空\n");
			else
				printf("队列不为空\n");
			break;
		case 0:
			Destroy_Queue(&que);
			printf("队列销毁成功\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

Queue.c

#include "Queue.h"


//初始化队列
void Init_Queue(Queue* ptr)
{
	assert(ptr); // ptr要解引用,不能为空指针

	ptr->head = ptr->tail = NULL;
}



//销毁队列
void Destroy_Queue(Queue* ptr)
{
	assert(ptr); // ptr要解引用,不能为空指针

	QNode* cur = ptr->head;

	while (ptr->head != NULL)
	{
		cur = ptr->head;
		ptr->head = ptr->head->next;
		free(cur);
	}

	ptr->tail = NULL; // 所有空间释放完后尾指针要置空,不然就是野指针
}



//开辟新节点
QNode* Buy_Node()
{
	QNode* tmp = (QNode*)malloc(sizeof(QNode));

	return tmp;
}



//打印队列里面的数据
void Print_Queue(Queue* ptr)
{
	assert(ptr); // ptr要解引用,不能为空指针

	QNode* cur = ptr->head;

	while (cur != NULL)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}

	printf("\n");
}



//数据入队列
void Push_Queue(Queue* ptr,QDatatype val)
{
	assert(ptr); // ptr要解引用,不能为空指针

	QNode* newnode = Buy_Node();

	if (newnode == NULL) // 可能开辟空间失败,失败会返回NULL,则终止后面的程序
	{
		perror("Push_Queue\n");
		exit(1);
	}

	newnode->data = val; // 新节点要初始化好,把要储存的值赋进去
	newnode->next = NULL;

	if (ptr->head == NULL) //当队列为空时,头节点和尾节点都要赋值
	{
		ptr->head = ptr->tail = newnode;
	}
	else
	{
		ptr->tail->next = newnode;
		ptr->tail = newnode;
	}
}



//获取队列储存的元素个数
int Queue_Size(Queue* ptr)
{
	assert(ptr); // ptr要解引用,不能为空指针

	int count = 0;
	QNode* cur = ptr->head;

	while (cur != NULL)
	{
		cur = cur->next;
		count++;
	}

	return count;
}



//数据出队列
void Pop_Queue(Queue* ptr)
{
	assert(ptr); // ptr要解引用,不能为空指针

	if (ptr->head == NULL)
	{
		printf("队列中没有元素\n");
		return;
	}

	if (Queue_Size(ptr) == 1)
	{
		free(ptr->tail);//如果删完了但是没有将tail置为NULL,则case 5 会发生错误,显示队尾元素随机值。
		ptr->tail = NULL;
		ptr->head = NULL;
		return;
	}

	QNode* pop = ptr->head;
	ptr->head = ptr->head->next;

	free(pop);
}



//获取队头的数据
QDatatype Queue_Front(Queue* ptr)
{
	assert(ptr); // ptr要解引用,不能为空指针

	return ptr->head->data;
}



//获取队尾的数据
QDatatype Queue_Back(Queue* ptr)
{
	assert(ptr); // ptr要解引用,不能为空指针

	return ptr->tail->data;
}



//判断队列是否为空
int Check_Empty(Queue* ptr)
{
	assert(ptr); // ptr要解引用,不能为空指针

	if (Queue_Size(ptr))
		return 0;
	else
		return 1;
}

Queue.h

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

typedef int QDatatype;  // 队列储存的数据类型

typedef struct QNode
{
	struct QNode* next; // 指向下一个节点
	QDatatype data;		// 节点储存的数据
}QNode;

typedef struct Queue
{
	QNode* head;		//指向队列的第一个节点
	QNode* tail;		//指向队列的最后一个节点
}Queue;


//初始化队列
void Init_Queue(Queue* ptr);


//打印队列里面的数据
void Print_Queue(Queue* ptr);


//数据入队列
void Push_Queue(Queue* ptr, QDatatype val);


//数据出队列
void Pop_Queue(Queue* ptr);


//获取队头的数据
QDatatype Queue_Front(Queue* ptr);


//获取队尾的数据
QDatatype Queue_Back(Queue* ptr);


//获取队列储存的元素个数
int Queue_Size(Queue* ptr);


//判断队列是否为空
int Check_Empty(Queue* ptr);


//销毁队列
void Destroy_Queue(Queue* ptr);

另外扩展了解一下,实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。环形队列可以使用数组实现,也可以使用循环链表实现(链表实现要更简单一点),在下一篇博客中讲解一下。

在这里插入图片描述

4.相关例题

选择题

1.以下( )不是队列的基本运算?
A 从队尾插入一个新元素
B 从队列中删除第i个元素
C 判断一个队列是否为空
D 读取队头元素的值
答案:B
解析:队列只能从队头删除元素。

2.下列关于队列的叙述错误的是( )
A.队列可以使用链表实现
B.队列是一种“先入先出”的数据结构
C.数据出队列时一定只影响尾指针
D.数据入队列时一定从尾部插入
答案:C
解析:出队操作,一定会影响头指针,如果出队之后,队列为空,会影响尾指针。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot与SpringMVC的区别

SpringBoot与SpringMVC的区别是什么&#xff1f; SpringBoot和SpringMVC是Java开发中常用的两个框架&#xff0c;它们都是由Spring框架所提供的&#xff0c;但在功能和使用方式上有着一些区别。本文将分别介绍SpringBoot和SpringMVC的特点和区别。 一、SpringBoot的特点&#…

第16章 基于结构的测试技术(白盒测试技术)

一、静态测试技术 &#xff08;一&#xff09;概述 不运行程序代码的情况下&#xff0c;通过质量准则或其他准则对测试项目进行检查的测试类型&#xff0c;人工或工具检查。 1、代码检查 2、编码规则检查 软件编码规范评测&#xff1a;源程序文档化、数据说明、语句结构、…

wpf线程中更新UI的4种方式

在wpf中&#xff0c;更新UI上面的数据&#xff0c;那是必经之路&#xff0c;搞不好&#xff0c;就是死锁&#xff0c;或者没反应&#xff0c;很多时候&#xff0c;都是嵌套的非常深导致的。但是更新UI的方式&#xff0c;有很多的种&#xff0c;不同的方式&#xff0c;表示的意思…

01-MySQL 基础篇笔记

一、MySQL 概述 1.1 数据库相关概念 数据库&#xff1a;&#xff08;DB&#xff1a;DataBase&#xff09; 存储数据的仓库&#xff0c;数据是有组织的进行存储 数据库管理系统&#xff1a;&#xff08;DBMS&#xff1a;DataBase Management System&#xff09; 操作和管理数…

论文阅读笔记(AAAI 20)Order Matters

个人博客地址 注&#xff1a;部分内容参考自GPT生成的内容 论文笔记&#xff1a;Order Matters&#xff08;AAAI 20&#xff09; 用于二进制代码相似性检测的语义感知神经网络 论文:《Order Matters: Semantic-Aware Neural Networks for Binary Code Similarity Detection》…

时间日志格式的统一和定制

返回当前格式的时间没有错误&#xff0c;但是不符合中国人的阅读习惯 解决&#xff1a; 方案一&#xff1a;JsonFormat 解决后端 传到 前端格式问题 依赖&#xff1a; <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jack…

基于MQTT通信开发的失物招领小程序

项目架构设计 这个项目采用前后端分离的方式&#xff0c;重新设计了两条链路来支撑程序的信息获取和传递 前端的小程序页面再启动页面渲染时&#xff0c;直接通过DBAPI从后端数据库获取信息&#xff0c;直接渲染在小程序中项目中给DBAPI的定位是快速从后端获取信息&#xff0…

C语言 计数控制循环

今天 我们来说 计数控制的循环 对于循环次数 我们已知的循环 我们称之为 计数控制的循环 这种情况 我们一般选择 for来实现 更为方便 先看一个案例 求 1 到 N 的累加合 我们代码可以这样写 #define _CRT_SECURE_NO_WARNINGS//禁用安全函数警告 #pragma warning(disable:6031…

一键自动化博客发布工具,chrome和firfox详细配置

blog-auto-publishing-tools博客自动发布工具现在已经可以同时支持chrome和firefox了。 很多小伙伴可能对于如何进行配置和启动不是很了解&#xff0c;今天带给大家一个详细的保姆教程&#xff0c;只需要跟着我的步骤一步来就可以无障碍启动了。 前提条件 前提条件当然是先下…

数据库MySQL的基本操作

在Linux里面&#xff0c;我们要对数据库MySQL进行操作时&#xff08;例如修改MySQL的密码&#xff09;&#xff0c;不是直接在我们的终端上进行操作&#xff0c;而是通过终端连接进入到MySQL里面去&#xff0c;在进行操作&#xff0c;写SQL语句。 而安装C等的开发库sudo命令&a…

【深度学习驱动的蛋白质设计技术与前沿实践-从基础到尖端应用】

RoseTTAFold&#xff0c;作为 David Baker 教授团队早期开发的蛋白质结构预测工具&#xff0c;在学术界与工 业界广受认可。然而&#xff0c;随着时间推移&#xff0c;仅局限于预测已知结构的蛋白质并不能满足生物医药和生 物工程领域对创新设计的需求。这促使 David Baker 教授…

浅谈ps/2键盘

文章目录 说明基础知识操作系统中断类型工作机制优点应用 CPU对IO设备的轮询机制轮询机制的工作原理轮询机制的特点轮询机制的优、缺点与中断机制的对比 N-Key Roller&#xff08;全键无冲&#xff09;应用领域实现原理技术限制 PS/2接口简介USB设备&PS/2设备的工作机制PS/…

【在线oj系统】02-开发环境版本说明

目录 一、前置环境版本介绍 二、SpringCloud组件停更/替换/更新 服务注册和发现 服务调用和负载均衡 分布式事务 服务熔断和降级 服务链路追踪 服务网关 分布式配置管理 三、客户端版本 一、前置环境版本介绍 使用Cloud的版本决定Boot的版本&#xff0c;SpringCloud的…

大语言模型从Scaling Laws到MoE

1、摩尔定律和伸缩法则 摩尔定律&#xff08;Moores law&#xff09;是由英特尔&#xff08;Intel&#xff09;创始人之一戈登摩尔提出的。其内容为&#xff1a;集成电路上可容纳的晶体管数目&#xff0c;约每隔两年便会增加一倍&#xff1b;而经常被引用的“18个月”&#xf…

【02358单片机原理及应用】第一、二章考试复习知识点期末复习自考复习

单片机原理及应用考试复习知识点 第1章 计算机基础知识 考试知识点&#xff1a; 1、各种进制之间的转换 &#xff08;1&#xff09;各种进制转换为十进制数 方法&#xff1a;各位按权展开相加即可。 &#xff08;2&#xff09;十进制数转换为各种进制 方法&#xff1a;整…

将VM虚拟机Ubuntu20.04系统扩容

一、拓展虚拟机硬盘空间 随着学习的深入&#xff0c;虚拟机里面的内容越来越多&#xff0c;我们可能会面临着硬盘空间不足的问题。今天我们就来沉浸式体验一把给虚拟机扩容。 二、拓展VM虚拟机硬盘前须知 在硬盘拓展时需要注意的一点是有快照的话拓展不了说是&#xff0c;先删除…

分类规则挖掘(一)

目录 一、分类问题概述&#xff08;一&#xff09;分类规则挖掘&#xff08;二&#xff09;分类规则评估&#xff08;三&#xff09;分类规则应用 二、k-最近邻分类法 一、分类问题概述 动物分类&#xff1a;设有动物学家陪小朋友林中散步&#xff0c;若有动物突然从小朋友身边…

深度学习500问——Chapter08:目标检测(7)

文章目录 8.3.8 RFBNet 8.3.9 M2Det 8.3.8 RFBNet RFBNet有哪些创新点 1. 提出RF block&#xff08;RFB&#xff09;模块 RFBNet主要想利用一些技巧使得轻量级模型在速度和精度上达到很好的trade-off的检测器。灵感来自人类视觉的感受野结构Receptive Fields&#xff08;RFs…

gin-vue-blog 前后端分离项目(已经部署)

gin-vue-blog 前台&#xff1a; 后台&#xff1a; 1.数据库设计&#xff1a;https://blog.csdn.net/m0_73337964/article/details/138137629?spm1001.2014.3001.5501 2.RESTFUL API路由实现&#xff1a;https://blog.csdn.net/m0_73337964/article/details/138321631?spm1…

5G Advanced and Release18简述

5G Advanced 5G-Advanced, formally defined in 3GPP Release 18, represents an upgrade to existing 5G networks. 先睹robot总结的5G Advanced的advancements: Enhanced Mobility and Reliability: 5G-Advanced will support advanced applications with improved mobility…