第 3 章 栈和队列(单链队列)

1. 背景说明

队列(queue)是一种先进先出(first in first out,缩为 FIFO)的线性表。它只允许在表的一端进行插入,而在另一端删除元素。

2. 示例代码

1)status.h

/* DataStructure 预定义常量和类型头文件 */#ifndef STATUS_H
#define STATUS_H/* 函数结果状态码 */
#define TRUE 					1			/* 返回值为真 */
#define FALSE 					0			/* 返回值为假 */
#define RET_OK 					0			/* 返回值正确 */
#define INFEASIABLE    		   	2			/* 返回值未知 */
#define ERR_MEMORY     		   	3			/* 访问内存错 */
#define ERR_NULL_PTR   			4			/* 空指针错误 */
#define ERR_MEMORY_ALLOCATE		5			/* 内存分配错 */
#define ERR_NULL_STACK			6			/* 栈元素为空 */
#define ERR_PARA				7			/* 函数参数错 */
#define ERR_OPEN_FILE			8			/* 打开文件错 */
#define ERR_NULL_QUEUE			9			/* 队列为空错 */
typedef int Status;							/* Status 是函数的类型,其值是函数结果状态代码,如 OK 等 */
typedef int Bollean;						/* Boolean 是布尔类型,其值是 TRUE 或 FALSE */#endif // !STATUS_H

2) linkQueue.h

/* 单链队列 —— 队列的链式存储结构头文件 */#ifndef LINKQUEUE_H
#define LINKQUEUE_H#include "status.h"typedef int QElemType;typedef struct QNode {QElemType data;struct QNode *next;
} QNode, *QueuePtr;typedef struct {QueuePtr front, rear;
} LinkQueue;/* 构造一个空队列 Q */
Status InitQueue(LinkQueue *Q);/* 销毁队列 Q(无论空否均可) */
Status DestroyQueue(LinkQueue *Q);/* 将 Q 清为空队列 */
Status ClearQueue(LinkQueue *Q);/* 若 Q 为空队列,则返回 TRUE,否则返回 FALSE */
Bollean QueueEmpty(const LinkQueue *Q);/* 求队列的长度 */
int QueueLength(LinkQueue *Q);/* 若队列不空,则用 e 返回 Q 的队头元素,并返回 OK, 否则返回 ERROR */
Status GetQueueHead(const LinkQueue *Q, QElemType *e);/* 插入元素 e 为 Q 的新的队尾元素 */
Status EnQueue(LinkQueue *Q, QElemType e);/* 若队列不空,删除 Q 的队头元素,用 e 返回其值,并返回 OK, 否则返回 ERROR */
Status DeQueue(LinkQueue *Q, QElemType *e);/* 从队头到队尾依次对队列 Q 中每个元素调用函数 vi() */
Status QueueTraverse(const LinkQueue *Q, void(*vi)(QElemType));#endif // !LINKQUEUE_H

3) linkQueue.c

/* 单链队列 —— 队列的链式存储结构源文件 */#include "linkQueue.h"
#include <stdio.h>
#include <stdlib.h>/* 构造一个空队列 Q */
Status InitQueue(LinkQueue *Q)
{Q->front = Q->rear = (QueuePtr)malloc(sizeof(QNode));if (!Q->front) {printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_MEMORY_ALLOCATE);return ERR_MEMORY_ALLOCATE;}Q->front->next = NULL;return RET_OK;
}/* 销毁队列 Q(无论空否均可) */
Status DestroyQueue(LinkQueue *Q)
{while (Q->front) {Q->rear = Q->front->next;free(Q->front);Q->front = Q->rear;}return RET_OK;
}/* 将 Q 清为空队列 */
Status ClearQueue(LinkQueue *Q)
{Q->rear = Q->front;QueuePtr p = Q->front->next;Q->front->next = NULL;QueuePtr q = NULL;while (p) {q = p;p = p->next;free(q);}return RET_OK;
}/* 若 Q 为空队列,则返回 TRUE,否则返回 FALSE */
Bollean QueueEmpty(const LinkQueue *Q)
{return (Q->front == Q->rear) ? TRUE : FALSE;
}/* 求队列的长度 */
int QueueLength(LinkQueue *Q)
{int length = 0;QueuePtr p = Q->front;while (p != Q->rear) {++length;p = p->next;}return length;
}/* 若队列不空,则用 e 返回 Q 的队头元素(队头元素为 front 的下一个元素), 并返回 OK, 否则返回 ERROR */
Status GetQueueHead(const LinkQueue *Q, QElemType *e)
{if (Q->front == Q->rear) {printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_QUEUE);return ERR_NULL_QUEUE;}*e = Q->front->next->data;return RET_OK;
}static QueuePtr MakeNewQueueNode(QElemType e)
{QueuePtr p = (QueuePtr)malloc(sizeof(QNode));if (!p) {printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_MEMORY_ALLOCATE);return NULL;}p->data = e;p->next = NULL;return p;
}/* 插入元素 e 为 Q 的新的队尾元素 */
Status EnQueue(LinkQueue *Q, QElemType e)
{QueuePtr p = MakeNewQueueNode(e);if (p == NULL) {printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_PTR);return ERR_NULL_PTR;}Q->rear->next = p;Q->rear = p;return RET_OK;
}/* 若队列不空,删除 Q 的队头元素,用 e 返回其值,并返回 OK, 否则返回 ERROR */
Status DeQueue(LinkQueue *Q, QElemType *e)
{if (Q->front == Q->rear) {printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_QUEUE);return ERR_NULL_QUEUE;}QueuePtr p = Q->front->next;*e = p->data;Q->front->next = p->next;if (Q->rear == p) {Q->rear = Q->front;}free(p);return RET_OK;
}/* 从队头到队尾依次对队列 Q 中每个元素调用函数 vi() */
Status QueueTraverse(const LinkQueue *Q, void(*vi)(QElemType))
{QueuePtr p = Q->front->next;while (p) {vi(p->data);p = p->next;}return RET_OK;
}

4) auxiliary.h

/* 辅助函数头文件 */#ifndef AUXILIARY_H
#define AUXILIARY_H#include "linkQueue.h"/* 打印栈元素 */
void Print(QElemType e);#endif // !AUXILIARY_H

5) auxiliary.c

/* 辅助函数实现源文件 */#include "auxiliary.h"
#include <stdio.h>/* 打印栈元素 */
void Print(QElemType e)
{printf("%d ", e);
}

6) main.c

/* 入口程序源文件 */#include "status.h"
#include "auxiliary.h"
#include "linkQueue.h"
#include <stdio.h>int main(void)
{LinkQueue Q;Status ret = InitQueue(&Q);if (ret == RET_OK) {printf("Initialize queue success!\n");}printf("The queue is %s\n", (QueueEmpty(&Q) == TRUE) ? "empty" : "not empty");printf("The length of the queue is %d\n", QueueLength(&Q));EnQueue(&Q, -5);EnQueue(&Q, 5);EnQueue(&Q, 10);printf("After insert 3 elements, the length of the queue is %d\n", QueueLength(&Q));printf("The queue is %s\n", (QueueEmpty(&Q) == TRUE) ? "empty" : "not empty");printf("The elements of the queue is: ");QueueTraverse(&Q, Print);printf("\n");QElemType e;ret = GetQueueHead(&Q, &e);if (ret == RET_OK) {printf("The element of the head of the queue is %d\n", e);}DeQueue(&Q, &e);printf("Delete the element of the head of the queue %d\n", e);ret = GetQueueHead(&Q, &e);if (ret == RET_OK) {printf("The new element of the head of the queue is %d\n", e);}ClearQueue(&Q);printf("After clear the queue, Q.front = %p, Q.rear = %p, Q.front->next = %p\n",Q.front, Q.rear, Q.front->next);DestroyQueue(&Q);printf("After destroy the queue, Q.front = %p, Q.rear = %p\n", Q.front, Q.rear);return 0;
}

3. 输出示例

注意:free() 函数的作用并不仅仅把内存释放,还将指针置为空。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【rust/egui】(七)看看template的app.rs:Slider

说在前面 rust新手&#xff0c;egui没啥找到啥教程&#xff0c;这里自己记录下学习过程环境&#xff1a;windows11 22H2rust版本&#xff1a;rustc 1.71.1egui版本&#xff1a;0.22.0eframe版本&#xff1a;0.22.0上一篇&#xff1a;这里 Slider 滑块&#xff0c;如下图 定义…

单片机-控制按键点亮LED灯

1、按键电路图 定义四个按键引脚 1、按键按下 为 输入为低电平 2、按键不按下 IO有上拉电阻&#xff0c;为高电平 // 定义 按键的 管教 sbit KEY1 P3^1; sbit KEY2 P3^0; sbit KEY3 P3^2; sbit KEY4 P3^3; 2、LED灯电路图 LED 输出高电平为亮 // 定义LED灯 管教 sbit LED1…

Web服务器部署上线踩坑流程回顾

5月份时曾部署上线了C的Web服务器&#xff0c;温故而知新&#xff0c;本篇文章梳理总结一下部署流程知识&#xff1b; 最初的解决方案&#xff1a;https://blog.csdn.net/BinBinCome/article/details/129750951?spm1001.2014.3001.5501后来的解决方案&#xff1a;https://blog…

海格里斯HEGERLS高密度料箱式四向穿梭车存储系统有哪些显著优势?

近些年仓储货架向着自动化、智能化发展&#xff0c;因此市面上出现很多不同类型的智能自动化仓储货架。其中&#xff0c;最受企业青睐的便是四向穿梭车货架。四向穿梭车货架根据其载重不同可分为托盘式和料箱式两大类。这两种不同类型的四向穿梭车货架在结构形式和控制方式上基…

微服务-gateway鉴权

文章目录 一、前言二、gateway鉴权1、依赖配置2、编写代码3、GlobalFilter详解3.1、GlobalFilter简介3.2、GlobalFilter自定义执行顺序3.2.1、实现Order接口实现自定义执行顺序 一、前言 网关是介于客户端和服务器端之间的中间层&#xff0c;所有的外部请求都会先经过 网关这一…

深入了解Docker镜像操作

Docker是一种流行的容器化平台&#xff0c;它允许开发者将应用程序及其依赖项打包成容器&#xff0c;以便在不同环境中轻松部署和运行。在Docker中&#xff0c;镜像是构建容器的基础&#xff0c;有些家人们可能在服务器上对docker镜像的操作命令不是很熟悉&#xff0c;本文将深…

【LeetCode-中等题】200. 岛屿数量

文章目录 题目方法一&#xff1a;深度优先搜索 dfs方法二&#xff1a;广度优先搜索 bfs方法三&#xff1a;&#xff08;重点掌握&#xff09;并查集 题目 方法一&#xff1a;深度优先搜索 dfs 思路&#xff1a;让一个扫描指针扫描每一个格子&#xff0c;然后每扫到一个为1的格…

Spring Boot日志基础使用 设置日志级别

然后 我们来说日志 日志在实际开发中还是非常重要的 即可记录项目状态和一些特殊情况发生 因为 我们这里不是将项目 所以 讲的也不会特别深 基本还是将Spring Boot的日志设置或控制这一类的东西 相对业务的领域我们就不涉及了 日志 log 初期最明显的作用在于 开发中 你可以用…

element+vue table表格全部数据和已选数据联动

1.组件TableChoose <template><div class"tableChooseBox"><div class"tableRow"><div class"tableCard"><div class"tableHeadTip">全部{{ labelTitle }}</div><slot name"body" …

OpenCV(十三):图像中绘制直线、圆形、椭圆形、矩形、多边形和文字

目录 1.绘制直线line() 2.绘制圆形circle() 3.绘制椭圆形ellipse() 4.绘制矩形rectangle() 5.绘制多边形 fillPoly() 6.绘制文字putText() 7.例子 1.绘制直线line() CV_EXPORTS_W void line(InputOutputArray img,Point pt1, Point pt2,const Scalar& color,int t…

无涯教程-Android Studio函数

第1步-系统要求 您将很高兴知道您可以在以下两种操作系统之一上开始Android应用程序的开发- MicrosoftWindows10/8/7/Vista/2003(32或64位)MacOSX10.8.5或更高版本,最高10.9(小牛) GNOME或KDE桌面 第二点是,开发Android应用程序所需的所有工具都是开源的,可以从Web上下载。以…

vue的第2篇 第一个vue程序

一 环境的搭建 1.1常见前端开发ide 1.2 安装vs.code 1.下载地址&#xff1a;Visual Studio Code - Code Editing. Redefined 2.进行安装 1.2.1 vscode的中文插件安装 1.在搜索框输入“chinese” 2.安装完成重启&#xff0c;如下变成中文 1.2.2 修改工作区的颜色 选中[浅色]…