第 3 章 栈和队列 (循环队列)

1. 背景说明

和顺序栈相类似,在队列的顺序存储结构中,除了用一组地址连续的存储单元依次存放从队列头到队列尾的元素之外,

尚需附设两个指针 front 和 rear 分别指示队列头元素及队列尾元素的位置。约定:初始化建空队列时,令 fronts = rear = 0,

每当插入新的队列尾元素时,“尾指针增 1”;每当删除队列头元素时,“头指针增 1”。因此,在非空队列中,头指针始终指向

队列头元素,而尾指针始终指向队列尾元素的下一个位置。 

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			/* 队列为空错 */
#define ERR_FULL_QUEUE			10			/* 队列为满错 */
typedef int Status;							/* Status 是函数的类型,其值是函数结果状态代码,如 RET_OK 等 */
typedef int Bollean;						/* Boolean 是布尔类型,其值是 TRUE 或 FALSE */

#endif // !STATUS_H

2) cycleQueue.h

/* 循环队列实现头文件 */

#ifndef CYCLEQUEUE_H
#define CYCLEQUEUE_H

#include "status.h"

#define MAX_QUEUE_SIZE 5

typedef int QElemType;

typedef struct {
	QElemType *base;
	int front;
	int rear;
} SqQueue;

/* 构造一个空队列 Q */
Status InitQueue(SqQueue *Q);

/* 销毁队列 Q */
Status DestroyQueue(SqQueue *Q);

/* 将 Q 清为空队列 */
void ClearQueue(SqQueue *Q);

/* 若队列 Q 为空队列,则返回 TRUE,否则返回 FALSE */
Bollean QueueEmpty(const SqQueue *Q);

/* 返回 Q 的元素个数,即队列的长度 */
int QueueLength(const SqQueue *Q);

/* 若队列不空,则用 e 返回 Q 的队头元素,并返回 OK */
Status GetQueueHead(const SqQueue *Q, QElemType *e);

/* 插入元素 e 为 Q 的新的队尾元素 */
Status EnQueue(QElemType e, SqQueue *Q);

/* 若队列不空,则删除 Q 的队头元素,用 e 返回其值,并返回 OK */
Status DeQueue(SqQueue *Q, QElemType *e);

/* 从队头到队尾依次对队列 Q 中每个元素调用函数 vi() */
Status QueueTraverse(const SqQueue *Q, void(*vi)(QElemType));

#endif // !CYCLEQUEUE_H

3) cycleQueue.c

/* 循环队列实现源文件 */

#include "cycleQueue.h"
#include <stdio.h>
#include <stdlib.h>

static Bollean QueueFull(const SqQueue *Q)
{
	return (((Q->rear + 1) % MAX_QUEUE_SIZE) == Q->front) ? TRUE : FALSE;
}

/* 构造一个空队列 Q */
Status InitQueue(SqQueue *Q)
{
	Q->base = (QElemType *)malloc(sizeof(QElemType) * MAX_QUEUE_SIZE);
	if (!Q->base) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_MEMORY_ALLOCATE);
		return ERR_MEMORY_ALLOCATE;
	}

	Q->front = Q->rear = 0;

	return RET_OK;
}

/* 销毁队列 Q */
Status DestroyQueue(SqQueue *Q)
{
	if (Q->base) {
		free(Q->base);
	}

	Q->base = NULL;
	Q->front = Q->rear = 0;
	
	return RET_OK;
}

/* 将 Q 清为空队列 */
void ClearQueue(SqQueue *Q)
{
	Q->front = Q->rear = 0;
}

/* 若队列 Q 为空队列,则返回 TRUE,否则返回 FALSE */
Bollean QueueEmpty(const SqQueue *Q)
{
	return (Q->front == Q->rear) ? TRUE : FALSE;
}

/* 返回 Q 的元素个数,即队列的长度, 模运算可以起到类似于绝对值的作用 */
int QueueLength(const SqQueue *Q)
{
	return ((Q->rear - Q->front + MAX_QUEUE_SIZE) % MAX_QUEUE_SIZE);
}

/* 若队列不空,则用 e 返回 Q 的队头元素,并返回 OK */
Status GetQueueHead(const SqQueue *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->base + Q->front);

	return RET_OK;
}

/* 插入元素 e 为 Q 的新的队尾元素 */
Status EnQueue(QElemType e, SqQueue *Q)
{
	if (QueueFull(Q)) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_FULL_QUEUE);
		return ERR_FULL_QUEUE;
	}

	Q->base[Q->rear] = e;
	Q->rear = (Q->rear + 1) % MAX_QUEUE_SIZE;

	return RET_OK;
}

/* 若队列不空,则删除 Q 的队头元素,用 e 返回其值,并返回 OK */
Status DeQueue(SqQueue *Q, QElemType *e)
{
	if (QueueEmpty(Q)) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_QUEUE);
		return ERR_NULL_QUEUE;
	}

	*e = Q->base[Q->front];
	Q->front = (Q->front + 1) % MAX_QUEUE_SIZE;

	return RET_OK;
}

/* 从队头到队尾依次对队列 Q 中每个元素调用函数 vi() */
Status QueueTraverse(const SqQueue *Q, void(*vi)(QElemType))
{
	int pos = Q->front;
	while (pos != Q->rear) {
		vi(Q->base[pos]);
		pos = (pos + 1) % MAX_QUEUE_SIZE;
	}

	return RET_OK;
}

4) auxiliary.h

/* 辅助函数头文件 */

#ifndef AUXILIARY_H
#define AUXILIARY_H

#include "cycleQueue.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 "cycleQueue.h"
#include <stdio.h>

int main(void)
{
	SqQueue Q;
	int ret = InitQueue(&Q);
	if (ret != RET_OK) {
		printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret);
		return ret;
	}

	printf("After initialize the queue, the queue is %s\n",
		(QueueEmpty(&Q) == TRUE) ? "empty" : "not empty");
	printf("Please input the element of the queue, no more than %d elements(-1 to break): ",
		MAX_QUEUE_SIZE - 1);
	QElemType e;
	int length = 0;
	do {
		scanf_s("%d", &e);
		if (e == -1) {
			break;
		}

		ret = EnQueue(e, &Q);
		if (ret != RET_OK) {
			break;
		}

		++length;
	} while (length < MAX_QUEUE_SIZE - 1);

	printf("The length of the queue is %d\n", QueueLength(&Q));
	printf("The queue is %s\n", (QueueEmpty(&Q) == TRUE) ? "empty" : "not empty");
	printf("Delete from the head of the queue and insert into the rear of the queue for"
		" %d times:\n", MAX_QUEUE_SIZE);
	for (int i = 0; i < MAX_QUEUE_SIZE; ++i) {
		DeQueue(&Q, &e);
		printf("The elment deleted is %d, please input the element to be insert: ", e);
		scanf_s("%d", &e);
		EnQueue(e, &Q);
	}

	printf("The element of the queue is: ");
	QueueTraverse(&Q, Print);
	printf("\n");
	length = QueueLength(&Q);
	if (length - 2 > 0) {
		printf("Now delete %d elements of the queue in the head of the queue\n", length - 2);
	}

	while (QueueLength(&Q) > 2) {
		DeQueue(&Q, &e);
		printf("The element of the queue deleted is %d\n", e);
	}

	ret = GetQueueHead(&Q, &e);
	if (ret == RET_OK) {
		printf("Now the element of the head of the queue is %d\n", e);
	}

	ClearQueue(&Q);
	printf("After clear the queue, the queue is %s\n", (QueueEmpty(&Q) == TRUE) ? "empty" : "not empty");
	DestroyQueue(&Q);

	return 0;
}

3. 输出示例

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

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

相关文章

react17:生命周期函数

挂载时更新时 setState触发更新、父组件重新渲染时触发更新forceUpdate触发更新卸载时 react&#xff08;v17.0.2&#xff09;的生命周期图谱如下。 相较于16版本&#xff0c;17版本生命周期函数有如下变化&#xff1a; componentWillMount() componentWillUpdate() compone…

ICCV 2023 | 小鹏汽车纽约石溪:局部上下文感知主动域自适应LADA

摘要 主动域自适应&#xff08;ADA&#xff09;通过查询少量选定的目标域样本的标签&#xff0c;以帮助模型从源域迁移到目标域。查询数据的局部上下文信息非常重要&#xff0c;特别是在域间差异较大的情况下&#xff0c;然而现有的ADA方法尚未充分探索这一点。在本文中&#…

【德哥说库系列】-ASM管理Oracle 19C单实例部署

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

【2023研电赛】安谋科技企业命题三等奖作品: 短临天气预报AI云图分析系统

本文为2023年第十八届中国研究生电子设计竞赛安谋科技企业命题三等奖分享&#xff0c;参加极术社区的【有奖活动】分享2023研电赛作品扩大影响力&#xff0c;更有丰富电子礼品等你来领&#xff01;&#xff0c;分享2023研电赛作品扩大影响力&#xff0c;更有丰富电子礼品等你来…

【LeetCode】227. 基本计算器 II

227. 基本计算器 II&#xff08;中等&#xff09; 方法&#xff1a;双栈解法 思路 我们可以使用两个栈 nums 和 ops 。 nums &#xff1a; 存放所有的数字ops &#xff1a;存放所有的数字以外的操作 然后从前往后做&#xff0c;对遍历到的字符做分情况讨论&#xff1a; 空格 …

【项目经验】:elementui表格中表头的多选框换成文字

一.项目需求 表格可以多选&#xff0c;表头都是汉字。。。。类似于这种 二.实现功能 用到的方法 Table Attributes 参数说明类型可选值默认值header-cell-class-name表头单元格的 className 的回调方法&#xff0c;也可以使用字符串为所有表头单元格设置一个固定的 className。…

C++文件操作

一、fstream简介 C 提供了一组用于文件操作的标准库fstream&#xff0c;可以进行文件的读取、写入和其他相关操作。常用的文件操作包括文件的打开、关闭、读取、写入和定位等。下面是一些常见的文件操作函数&#xff1a; 文件的打开和关闭&#xff1a; std::ofstream&#x…

点可云进销存开源系统V6.0.1 ERP系统进销存源码仓库管理

介绍 点可云进销存系统&#xff0c;基于thinkphplayui开发。 功能包含&#xff1a;采购、销售、零售、多仓库管理、财务管理等功能 和超详细的报表功能&#xff08;采购报表、销售报表、零售报表、仓库报表、资金报表等&#xff09; 软件架构 thinkphplayui 功能概览 购货 -购…

LeetCode(力扣)236. 二叉树的最近公共祖先Python

LeetCode236. 二叉树的最近公共祖先 题目链接代码 题目链接 https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/ 代码 # Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val x # self.…

数据结构(Java实现)-排序

排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序&#xff…

4、DVWA——文件包含

文章目录 一、文件包含概述二、low2.1 源码分析2.2 通关分析 三、medium3.1 源码分析3.2 通关思路 四、high4.1 源码分析4.2 通关思路 五、impossible 一、文件包含概述 文件包含是指当服务器开启allow_url_include选项时&#xff0c;就可以通过php的某些特性函数&#xff08;i…

Spring Cloud--从零开始搭建微服务基础环境【三】

&#x1f600;前言 本篇博文是关于Spring Cloud–从零开始搭建微服务基础环境【三】&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;…

数据结构(Java实现)-Map和Set

搜索树 概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值 它的左右子树也…

【learnopengl】Assimp构建与编译

文章目录 【learnopengl】Assimp构建与编译1 前言2 Assimp构建与编译2.1 下载源码2.2 CMake构建2.3 VS2022编译 3 在VS中配置Assimp库4 验证 【learnopengl】Assimp构建与编译 1 前言 最近在跟着LearnOpenGL这个网站学习OpenGL&#xff0c;这篇文章详细记录一下教程中关于Ass…

Mac 如何判断下载Mac with Intel Chip 还是 Mac with Apple Chip

如下图&#xff0c;当我们在 Mac系统 下载客户端时&#xff0c;有两种选择&#xff1a;Mac with Intel Chip 、 Mac with Apple Chip 如何判断要下载哪一种&#xff1f; 需要判断本机Mac是在Inter芯片还是Apple芯片上运行的。方法如下&#xff1a; 点击屏幕左上角Apple标志&a…

ARM编程模型-常用指令集

一、ARM指令集 ARM是RISC架构&#xff0c;所有的指令长度都是32位&#xff0c;并且大多数指令都在一个单周期内执行。主要特点&#xff1a;指令是条件执行的&#xff0c;内存访问使用Load/store架构。 二、Thumb 指令集 Thumb是一个16位的指令集&#xff0c;是ARM指令集的功能…

测试人:“躺平?不可能的“, 盘点测试人在职场的优势

之前有这么一个段子&#xff1a;有人喜欢创造世界&#xff0c;他们做了程序员&#xff1b;有人喜欢拯救世界&#xff0c;他们做了测试员&#xff01;近几年&#xff0c;测试工程师在企业究竟是怎么样的发展&#xff1f;随着企业对于用户体验的满意度越来越重视&#xff0c;更加…

vue的第3篇 第一个vue程序

一 vue的mvvm实践者 1.1 介绍 Model&#xff1a;模型层&#xff0c; 在这里表示JavaScript对象 View&#xff1a;视图层&#xff0c; 在这里表示DOM(HTML操作的元素) ViewModel&#xff1a;连接视图和数据的中间件&#xff0c; Vue.js就是MVVM中的View Model层的实现者 在M…

不同路径【动态规划】

不同路径 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&#xff1f;…

【Java 基础篇】Java 数组使用详解:从零基础到数组专家

如果你正在学习编程&#xff0c;那么数组是一个不可或缺的重要概念。数组是一种数据结构&#xff0c;用于存储一组相同类型的数据。在 Java 编程中&#xff0c;数组扮演着非常重要的角色&#xff0c;可以帮助你组织、访问和操作数据。在本篇博客中&#xff0c;我们将从零基础开…