C语言数据结构之队列

news2024/11/17 14:21:26

目录

    • 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.cQueue.cQueue.h 三个文件进行实现,可以更加方便操作,也可以避免代码全放在一个文件中显得冗余。


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
解析:出队操作,一定会影响头指针,因为出队是删除队头元素,如果出队时队列只有一个元素,会影响头指针也会影响尾指针。

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

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

相关文章

Ubuntu系统安装nvfortran详细步骤【笔记】

实践设备&#xff1a;华硕FX-PRO&#xff08;NVIDIA GeForce GTX 960M&#xff09; Ubuntu系统安装NVFORTRAN&#xff08;NVIDIA Fortran Compiler&#xff09;步骤如下&#xff1a; 安装依赖项&#xff1a;在安装NVFORTRAN之前&#xff0c;你需要确保系统已经安装了一些必要…

IoTDB 入门教程 基础篇①——时序数据库为什么选IoTDB ?

文章目录 一、前文二、性能排行第一三、完全开源四、数据文件TsFile五、乱序数据高写入六、其他七、参考 一、前文 IoTDB入门教程——导读 关注博主的同学都知道&#xff0c;博主在物联网领域深耕多年。 时序数据库&#xff0c;博主已经用过很多&#xff0c;从最早的InfluxDB&a…

c语言刷题——输出图案

1.输出用“*”组成的X形图案 题目&#xff1a;请打印用“*”组成的X形图案 描述&#xff1a; 多组输入&#xff0c;一个整数&#xff08;2~20&#xff09;&#xff0c;表示输出的行数&#xff0c;也表示组成“X”的反斜线和正斜线的长度。 输出描述&#xff1a; 针对每行输…

一觉醒来 AI科技圈发生的大小事儿 05月04日

&#x1f4f3;CVPR 2024 Highlight | 基于单曝光压缩成像&#xff0c;不依赖生成模型也能从单张图像中重建三维场景 本文介绍了一种基于单曝光压缩成像&#xff08;SCI&#xff09;系统和神经辐射场&#xff08;NeRF&#xff09;的三维场景拍摄与重建方法&#xff0c;实现了不…

杭电acm2018 母牛的故事 Java解法 经典递归

标准递归题 先模拟 接着找递归出口 再找递归通式 想想看 今天的母牛等于前一天的母牛数加上今天出生的母牛 而三天前的母牛所有母牛都能生一头 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scnew Scanner(System.in);l…

单例、工厂、策略、装饰器设计模式

1. 单例模式&#xff08;Singleton Pattern&#xff09;&#xff1a; 单例模式是一种常用的设计模式&#xff0c;用于确保一个类只有一个实例&#xff0c;并提供一个全局访问点。这种模式的特点是类自己负责保存其唯一的实例&#xff0c;并控制其实例化过程。单例模式广泛应用…

(六)SQL系列练习题(下)#CDA学习打卡

目录 三. 查询信息 16&#xff09;检索"1"课程分数小于60&#xff0c;按分数降序排列的学生信息​ 17&#xff09;*按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩 18&#xff09;*查询各科成绩最高分、最低分和平均分 19&#xff09;*按各科成绩…

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

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

【C语言】分支和循环(上)

【C语言】分支和循环&#xff08;上&#xff09; 1、if语句1.2 else1.3分支中包含多条语句1.4嵌套if1.5悬空else问题 2、关系操作符3、条件操作符4、逻辑操作符&#xff1a;与、或、非&#xff08;取反&#xff09;&#xff08;&&&#xff0c;||&#xff0c;&#xff0…

从零开始学AI绘画,万字Stable Diffusion终极教程(五)

【第5期】ControlNet 欢迎来到SD的终极教程&#xff0c;这是我们的第五节课 这套课程分为六节课&#xff0c;会系统性的介绍sd的全部功能&#xff0c;让你打下坚实牢靠的基础 1.SD入门 2.关键词 3.Lora模型 4.图生图 5.controlnet 6.知识补充 在SD里面&#xff0c;想要…

Mysql复习笔记: 基础概念(待补充)

一. 基础概念 通用概念: 网络连接必须得分配给一个线程去进行处理&#xff0c;由一个线程来监听请求以及读取请求数据&#xff0c;比如从网络连接中读取和解析出来一条我们的系统发送过去的SQL语句 在数据库中&#xff0c;哪怕执行一条SQL语句&#xff0c;其实也可以是一个独立…

FLIR LEPTON3.5 热像仪wifi 科研实验测温采集仪

点击查看详情!点击查看详情点击查看详情点击查看详情点击查看详情点击查看详情点击查看详情点击查看详情点击查看详情点击查看详情点击查看详情点击查看详情点击查看详情点击查看详情点击查看详情 1、描述 这是一款桌面科研实验测温热成像多功能热像记录仪&#xff0c;小巧轻便…

【C/C++】

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

## 01深度学习介绍与安装PyTorch

文章目录 深度学习的发展历史和基本概念早期历史兴起与发展基本概念 如何安装和设置PyTorch环境系统要求安装步骤验证安装 结语 深度学习的发展历史和基本概念 深度学习&#xff0c;一种通过使用具有多层结构的神经网络来学习数据的复杂模型的机器学习技术&#xff0c;近年来已…

Scikit是什么?

目录 一、Scikit是什么&#xff1f; 二、用Scikit做一个简单房价预测例子 三、sklearn知识点 一、Scikit是什么&#xff1f; Scikit就是scikit-learn&#xff0c;是一个免费软件机器学习库。 https://scikit-learn.org/stable/https://scikit-learn.org/stable/ 用于预测数…

ubuntu20配置深度学习环境

目录 系统环境安装anaconda文件的安装anaconda环境配置anaconda换中科大源常用的anaconda命令 安装显卡驱动安装CUDA下载cudnn安装pytorch更换conda源选择对应的pytorch版本进行安装 系统环境 ubuntu20&#xff0c;安装了ros noetic。 参考博客主要有&#xff1a; https://g…

【Spring】JdbcTemplate

JdbcTemplate 是 Spring 提供的一个 JDBC 模板类&#xff0c;是对 JDBC 的封装&#xff0c;简化 JDBC 代码 也可以让 Spring 集成其它的 ORM 框架&#xff0c;例如&#xff1a;MyBatis、Hibernate 等 使用 JdbcTemplate 完成增删改查 一、环境准备 数据库&#xff1a; 准备…

C++相关概念和易错语法(11)(npos、string的基本使用)

本文主要是分享一些基础的用法和接口&#xff0c;不会涉及迭代器版本&#xff0c;也没有底层概念&#xff0c;主要是保证简单入门和使用。 1.npos string本质上是一个类&#xff0c;里面包含了上百个成员函数&#xff0c;在调用这个头文件后&#xff0c;我们要知道整个类都被…

OpenCV 为轮廓创建边界框和圆(62)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇:OpenCV检测凸包(61) 下一篇 :OpenCV如何为等值线创建边界旋转框和椭圆(62) ​ 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 cv::boundingRect使用 OpenCV 函数 cv::mi…

foobar2000 for Mac:卓越音乐播放器

当您在寻找一款音质卓越、功能丰富的音频播放器时&#xff0c;foobar2000 for Mac无疑是您的首选。它拥有简洁明了的界面设计&#xff0c;易于上手&#xff0c;同时支持多种音频格式&#xff0c;让您无需担心兼容性问题。 foobar2000 for Mac v2.6.4免激活版下载 foobar2000 fo…