C语言数据结构之队列

embedded/2024/9/23 13:53:29/

目录

    • 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");elseprintf("队列不为空\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;elsereturn 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.ppmy.cn/embedded/33071.html

相关文章

php中常用的数据类型汇总

在 PHP 中&#xff0c;常用的数据类型主要有以下几种&#xff1a; 标量类型&#xff08;Scalar Types&#xff09; integer&#xff08;整型&#xff09;&#xff1a;用于存储整数&#xff0c;可以是正数或负数。float&#xff08;浮点型/双精度型&#xff09;&#xff1a;用于…

Qt 配置 OpenCV

MinGW CMake 下载 OpenCV 源代码 使用 CMake 生成 OpenCV 的 Makefile // 设置源码 Where is the source code: C:\Program Files\OpenCV\source // 生成路径 C:\Program Files\OpenCV\build点击 Configure&#xff0c;设置编译器 Specify the generator for this project:…

JVM-02

字节码文件是一种特殊的文件格式&#xff0c;它包含了将源代码转换为机器可执行代码所需的指令集。字节码文件通常是由编译器将源代码编译为字节码的中间表示形式。 在Java中&#xff0c;字节码文件的扩展名为.class&#xff0c;它存储了编译后的Java代码。这些字节码文件可以在…

vue设置必填项

表单&#xff1a; <el-form-item label"标题" prop"title" ><el-input placeholder"标题" v-model"form.title"></el-input></el-form-item> 在data中添加一个rules来规定 rules: {title: [{ required: t…

Golang日志管理精讲:`log`库的高级用法与性能优化

Golang日志管理精讲&#xff1a;log库的高级用法与性能优化 引言log库概览核心组件介绍日志级别的设置标准Logger与自定义Logger 基础用法创建基础日志实例日志级别的设置标准Logger与自定义Logger 高级技巧日志格式自定义多日志文件分流集成系统服务中的日志管理 并发与性能优…

【Nginx 开发】反向代理配置,负载均衡配置,动静分离配置

nginx 配置 反向代理配置负载均衡配置动静分离 反向代理 我们根据实例进行讲解&#xff0c;效果是通过在浏览器访问www.hlh.com,跳转到Linux系统的tomcat主页面中 第一步&#xff1a;在windows系统的host文件进行域名和ip对应关系的配置 在host文件中添加自己的地址映射 192.…

大语言模型从Scaling Laws到MoE

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

C++关联容器1——map,multimap,set,multiset介绍,pair类型

目录 关联容器 使用关联容器 使用map 使用set 关联容器概述 定义关联容器 初始化multimap或multiset 关键字类型的要求 有序容器的关键字类型 使用关键字类型的比较函数 pair 类型 创建pair 对象的函数 关联容器 关联容器支持高效的关键字查找和访问。 两个主要的关…