栈和队列<数据结构 C版>

news2024/11/13 15:50:15

目录

栈(Stack)

栈的结构体

初始化

销毁

入栈

判空

出栈

取栈顶元素

获取栈个数

测试:

队列(Queue)

队列的结构体

单个结点

队列

初始化

销毁

入队列,队尾

判空

出队列,队头

取队头数据

取队尾数据(非标准操作)

获取队列个数

测试:


栈(Stack)

栈是一种特殊的线性表,其只允许在特定的一端进行插入和删除操作。

进行插入和删除操作的一端叫做栈顶

另一端称为栈底

栈中的数据元素遵循后进先出LIFO(Last In First Out )的原则

压栈:栈的插入操作也被称为进栈、入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈,出数据也在栈顶。

因为栈只在一端进行操作,所以栈的实现使用数组更加优越。


栈的结构体

//重命名,方便统一修改
typedef int STDataType;

typedef struct stack {
	STDataType* arr;
	int capacity;//栈的容量
	int top;//栈顶位置(有效元素个数)
}ST;

初始化

//初始化
void STInit(ST* ps) {
	assert(ps);//不能传入NULL
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}

销毁

//销毁
void STDestory(ST* ps) {
	assert(ps);//不能传入NULL
	if (ps->arr) {//防止对NULL指针的引用(即栈为空的情况)
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}

入栈

//入栈
void STPush(ST* ps, STDataType x) {
	assert(ps);
	if (ps->capacity == ps->top) {//若空间不足
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		//若栈容量为0,给定初始值,否则以两倍大小增长
		STDataType* p = (STDataType*)realloc(ps->arr, newcapacity * sizeof(STDataType));
		if (!p) {//申请失败,直接返回
			perror("realloc fail!");
			exit(1);
		}
		ps->arr = p;
		ps->capacity = newcapacity;//改变原容量大小
	}
	ps->arr[ps->top++] = x;//先给栈顶赋值,在加加
}

判空

//判空
bool STEmpty(ST* ps) {
	assert(ps);
	return ps->top == 0;//返回bool值,直接返回比较运算符的返回值
}

出栈

//出栈
void STPop(ST* ps) {
	assert(ps && !STEmpty(ps));//不能传入NULL && 栈为空
	ps->top--;//出栈,让栈顶减减
}

取栈顶元素

//取栈顶元素
STDataType STTop(ST* ps) {
	assert(ps && !STEmpty(ps));//不能传入NULL && 栈为空
	return ps->arr[ps->top - 1];//返回栈顶元素,让栈顶减减
}

获取栈个数

//获取栈有多少元素
int STSize(ST* ps) {
	assert(ps);
	return ps->top;//直接返回栈顶下标(即元素个数)
}

测试:


队列(Queue)

队列也是一种特殊的线性表,其在一端进行插入操作,另一端进行删除操作。

进行插入操作的一端叫做队尾(rear)。

进行删除操作的一端叫做队头(front)。

队列中的数据元素遵循后进先出FIFO(Frist In First Out )的原则

入队:队列的插入操作,一般发生在队尾

出队:队列的删除操作,一般发生在队头

因为队列在头部删除数据,使用数组,移动数据的时间复杂比较高,所以使用链表更优越。


队列的结构体

单个结点
//重命名,方便统一修改
typedef int QDataType;

//队列单个结点结构
typedef struct QueueNode {
	QDataType data;//数据
	struct QueueNode* next;//下一个结点
}QN;
队列
//队列结构
typedef struct queue {
	QN* front;//队头
	QN* rear;//队尾
	int size;//结点数
}Q;

初始化

//初始化队列
void QueueInit(Q* pq) {
	assert(pq);
	pq->front = pq->rear = NULL;
	pq->size = 0;
}

销毁

//销毁
void QueueDestory(Q* pq) {
	assert(pq);
	assert(!QueueEmpty(pq));//队列为空,不用销毁
	QN* pcur = pq->front;
	while (pcur) {
		QN* next = pcur->next;
		free(pcur);//依次释放每一个结点
		pcur= next;
	}
	pq->rear = pq->front = NULL;//置队头队尾
	pq->size = 0;
}

入队列,队尾

//入队列,队尾
void QueuePush(Q* pq, QDataType x) {
	assert(pq);
	QN* node = (QN*)malloc(sizeof(QN));//开辟一个新结点
	if (!node) {//防止为空
		perror("malloc fail!");
		exit(1);
	}
	node->data = x;//data元素
	node->next = NULL;//next指针
	if (pq->front == NULL) {//若队列为空,队头队尾都要改变
		pq->front = pq->rear = node;
	}
	else {//若不为空,则改变尾结点指向
		pq->rear->next = node;
		pq->rear = node;
	}
	pq->size++;//队列元素++
}

判空

//判空
bool QueueEmpty(Q* pq) {
	assert(pq);
	return pq->size == 0;
}

出队列,队头

//出队列,队头
void QueuePop(Q* pq) {
	assert(pq);
	assert(!QueueEmpty(pq));//不能为空
	if (pq->front->next == NULL) {//若只有一个元素,队尾的指向也要发生改变
		free(pq->front);
		pq->front = pq->rear = NULL;
	}
	else {//若有多个元素,只用改变队头指向
		QN* del = pq->front;
		pq->front = pq->front->next;
		free(del);
		del = NULL;
	}
	pq->size--;
}

取队头数据

//取队头数据
QDataType QueueFront(Q* pq) {
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->front->data;
}

取队尾数据(非标准操作)

//取队尾数据
QDataType QueueRear(Q* pq) {
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->rear->data;
}

获取队列个数

//队列有效个数
int QueueSize(Q* pq) {
	assert(pq);
	return pq->size;
}

测试:

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

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

相关文章

【YashanDB知识库】开源调度框架Quartz写入Boolean值到YashanDB报错

问题现象 Quartz 是一个广泛应用于企业级应用中的开源作业调度框架,它主要用于在Java环境中管理和执行任务。 为了任务调度,Quartz的数据模型中使用了大量的布尔值记录任务、流程的各种状态,如: Quartz使用JDBC写入任务状态代码…

【资料分享】2024第三届钉钉杯大学生大数据挑战赛B题思路解析+双语言代码

2024钉钉杯大学生大数据挑战赛,B题解题思路和双语言代码分享,资料预览:

制作excel模板,用于管理后台批量导入船舶数据

文章目录 引言I 数据有效性:基于WPS在Excel中设置下拉框选择序列内容II 数据处理:基于easyexcel工具实现导入数据的持久化2.1 自定义枚举转换器2.2 ExcelDataConvertExceptionIII 序列格式化: 基于Sublime Text 文本编辑器进行批量字符操作引言 需求: excel数据导入模板制…

【MySQL进阶之路 | 高级篇】表级锁之S锁,X锁,意向锁

1. 从数据操作的粒度划分:表级锁,页级锁,行锁 为了尽可能提高数据库的并发度,每次锁定的数据范围越小越好,理论上每次只锁定当前操作的数据的方案会得到最大的并发度,但是管理锁是很耗资源的事情&#xff…

前端开发:HTML与CSS

文章目录 前言1.1、CS架构和BS架构1.2、网页构成 HTML1.web开发1.1、最简单的web应用程序1.2、HTTP协议1.2.1 、简介1.2.2、 http协议特性1.3.3、http请求协议与响应协议 2.HTML概述3.HTML标准结构4.标签的语法5.基本标签6.超链接标签6.1、超链接基本使用6.2、锚点 7.img标签8.…

【网络安全的神秘世界】文件包含漏洞

🌝博客主页:泥菩萨 💖专栏:Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 一、概述 文件包含:重复使用的函数写在文件里,需要使用某个函数时直接调用此文件,而无需再…

【学习日记】函数调用 和 全局变量 如何实现 位置无关码

问题来源 在 I.MX6ull 的启动流程中,u-boot会将自身从内存一开始的位置拷贝到其他位置,以便给linux留出内存空间,防止 u-boot被覆盖如果代码中包含直接引用其链接时地址的指令,那么当代码被移动到新的地址时,这些引用…

聊聊RNNLSTM

RNN 用于解决输入数据为,序列到序列(时间序列)数据,不能在传统的前馈神经网络(FNN)很好应用的问题。时间序列数据是指在不同时间点上收集到的数据,这类数据反映了某一事物、现象等随时间的变化状态或程度,即输入内容的上下文关联…

工业现场实测,焦化厂导烟车与装煤车风机实现无人作业

一、项目背景 作为我国重要的能源行业之一,焦化行业在国民经济中扮演着重要角色,焦化工艺是高温、高压、有毒物质等因素共同作用下进行的,因此存在着安全隐患,并伴有环境污染,改善焦化工艺的安全和环保问题是当前亟待…

优选算法之前缀和(下)

目录 一、和为 k 的子数组 1.题目链接:560. 和为 K 的子数组 2.题目描述: 3.解法(前缀和 哈希表) 🌻算法思路: 🌻算法代码: 二、和可被 k 整除的子数组 1.题目链接&#xff…

MySQL中多表查询之外连接

首先先来介绍一下我做的两个表,然后再用他们两个举例说明。 -- 创建教师表 create table teachers( id_t int primary key auto_increment, -- 老师编号 name_t varchar(5) -- 姓名 ); -- 创建学生表 create table students( id_s int primary key auto_increment,…

Android APK混淆处理方案分析

这里写目录标题 一、前言1.1 相关工具二、Apk 分析2.1 apk 解压文件2.2 apk 签名信息2.3 apk AndroidManifest.xml2.4 apk code三、Apk 处理3.1 添加垃圾文件3.2 AndroidManifest.xml 处理3.3 dex 混淆处理3.4 zipalign对齐3.5 apk 重新签名3.6 apk 安装测试四、总结一、前言 提…

使用Astro+Vercel+Cloudflare一天时间开发部署上线一个知识博客网站,简直简简单单

大家好,这里是程序猿代码之路。在当今数字化时代,拥有一个个人博客网站对于分享知识、展示个人品牌变得越来越重要。然而,许多非技术背景的用户对于搭建和维护一个网站可能会感到望而却步。幸运的是,随着低代码和无代码平台的兴起…

Spring高手之路21——深入剖析Spring AOP代理对象的创建

文章目录 创建代理对象核心动作的三个步骤1. 判断 Bean 是否需要增强(源码分析时序图说明)2. 匹配增强器 Advisors(源码分析时序图说明)3. 创建代理对象(源码分析时序图说明) 创建代理对象核心动作的三个步…

C++模版基础知识与STL基本介绍

目录 一. 泛型编程 二. 函数模板 1. 概念 2. 函数模版格式 3. 函数模版的原理 4. 模版函数的实例化 (1). 隐式实例化 (2.) 显式实例化 5. 模版参数的匹配原则 三. 类模板 1. 类模板的定义格式 2. 类模板的实例化 四. STL的介绍 1. 什么是STL? 2. STL的版…

netty入门-7 ByteBuf

文章目录 前言ByteBuf结构池化与非池化创建(直接内存/堆内存)写入和读取释放零拷贝,slice,duplicate, copy,Composite 结语 前言 ByteBuf这部分视频讲的更为详细。 主要参考视频。 ByteBuf 结构 首先这…

C# Task.WaitAll 的用法

目录 简介 1.WaitAll(Task[], Int32, CancellationToken) 2.WaitAll(Task[]) 3.WaitAll(Task[], Int32) 4.WaitAll(Task[], CancellationToken) 5.WaitAll(Task[], TimeSpan) 结束 简介 Task.WaitAll 是 C# 中用于并行编程的一个的方法,它属于 System.Threa…

开始尝试从0写一个项目--后端(三)

器材管理 和员工管理基本一致,就不赘述,展示代码为主 新增器材 表设计: 字段名 数据类型 说明 备注 id bigint 主键 自增 name varchar(32) 器材名字 img varchar(255) 图片 number BIGINT 器材数量 comment VARC…

Elasticsearch 使用误区之三——分片设置不合理

Elasticsearch 是一个强大的搜索和分析引擎,它通过将数据分散到多个节点的分片中来进行分布式处理。 本文将探讨分片大小和策略的概念,以优化 Elasticsearch 的性能并防止过度分片或分片过大等问题。 先看个分片设置不合理的真实企业案例: 10…

陶晶驰串口屏使用记录与教程

首先把串口屏想象成和正点原子usmart调试程序一样的程序,串口屏主芯片有些是GD32 STM32都是主流单片机,里面下载了一些固件形成了现在的操作系统 其实我更喜欢把他们(usmart,串口屏主程序,micropython,at指…