数据结构——栈的实现(动态增长版本)

news2024/11/15 16:50:07

在这里插入图片描述

堆栈(stack)又称为栈或堆叠,是计算机科学中的一种抽象资料类型,只允许在有序的线性资料集合的一端(称为堆栈顶端,top)进行加入数据(push)和移除数据(pop)的运算。因而按照后进先出(LIFO, Last In First Out)的原理运作,堆栈常用一维数组或链表来实现。常与另一种有序的线性资料集合队列相提并论。
在这里插入图片描述
在这里插入图片描述

// 初始化栈
void StackInit(Stack* ps)
{
	assert(ps);
	ps->_a = (STDataType*)malloc(sizeof(STDataType)*4);
	if (ps->_a == NULL)
	{
		perror("malloc fail");
		return;
	}
	ps->_capacity = 4;
	ps->_top = 0;//top是栈顶元素的下一个位置
	//ps->_top = -1;//top是栈顶元素位置
}

这段代码实现了栈的初始化操作,具体实现如下:

首先,使用assert宏函数检查传入的栈指针ps是否为空,如果为空则程序终止。
接着,使用malloc函数为栈分配初始空间,这里分配了4个元素大小的空间,如果分配失败则输出错误信息并返回。
然后,将分配的空间大小4赋值给栈的容量_capacity。
最后,将栈顶元素的下一个位置初始化为0,即_top = 0。
需要注意的是,这里的栈实现是使用数组来模拟的,_a指向的是数组的首地址。同时,栈的容量是可动态扩展的,当栈空间不足时会自动扩展。

// 入栈
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	if (ps->_top == ps->_capacity)
	{
		STDataType* tmp = (STDataType*)realloc(ps->_a,sizeof(STDataType) * ps->_capacity*2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		ps->_a = tmp;
		ps->_capacity *= 2;
	}
	ps->_a[ps->_top] = data;
	ps->_top++;
}

这段代码实现了栈的入栈操作,具体实现如下:

首先,使用assert宏函数检查传入的栈指针ps是否为空,如果为空则程序终止。
接着,判断栈是否已满,即_top是否等于_capacity,如果已满则需要进行扩容操作。
如果需要扩容,使用realloc函数重新分配空间,将原空间大小扩大一倍。如果分配失败则输出错误信息并返回。
将新分配的空间地址存储在tmp指针中,并将原来的空间指针_a指向tmp指针。
将栈的容量_capacity乘以2,表示容量已扩大为原来的2倍。
将待入栈的元素data存储在栈顶位置,即_a[_top]。
将栈顶指针_top加1,指向下一个位置。
需要注意的是,这里的入栈操作实现的是动态扩容的栈,当栈满时会自动扩容。同时,入栈操作是将元素存储在栈顶位置,然后将栈顶指针_top加1,指向下一个位置,即栈顶指针指向的是下一个空闲的位置。

// 出栈
void StackPop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->_top--;
}

这段代码实现了栈的出栈操作,具体实现如下:

首先,使用assert宏函数检查传入的栈指针ps是否为空,如果为空则程序终止。
然后,使用assert宏函数检查栈是否为空,即栈顶指针_top是否为0,如果为空则程序终止。
将栈顶指针_top减1,表示栈顶元素已出栈。
需要注意的是,这里的出栈操作只是将栈顶指针_top减1,而没有实际删除栈顶元素。如果需要删除栈顶元素,可以在操作结束后手动释放元素所占用的空间。

// 获取栈顶元素
STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->_a[ps->_top - 1];
}

这段代码实现了获取栈顶元素的操作,具体实现如下:

首先,使用assert宏函数检查传入的栈指针ps是否为空,如果为空则程序终止。
然后,使用assert宏函数检查栈是否为空,即栈顶指针_top是否为0,如果为空则程序终止。
返回栈顶元素,即_a[_top-1],表示栈顶元素的值。
需要注意的是,这里的获取栈顶元素操作并不会将元素出栈,仅仅是获取栈顶元素的值。如果需要删除栈顶元素,请先调用出栈操作,再获取新的栈顶元素。

// 获取栈中有效元素个数
int StackSize(Stack* ps)
{
	assert(ps);
	return ps->_top;
}

这段代码实现了获取栈中有效元素个数的操作,具体实现如下:

首先,使用assert宏函数检查传入的栈指针ps是否为空,如果为空则程序终止。
返回栈中有效元素的个数,即栈顶指针_top的值。
需要注意的是,这里的栈中有效元素个数并不是栈的容量,而是栈中实际存储的元素个数。

// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
bool StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->_top == 0;
}

这段代码实现了检测栈是否为空的操作,具体实现如下:

首先,使用assert宏函数检查传入的栈指针ps是否为空,如果为空则程序终止。
判断栈是否为空,即栈顶指针_top是否为0,如果为0则说明栈为空,返回非零结果,否则返回0。
需要注意的是,这里的检测栈是否为空操作是通过判断栈顶指针_top是否为0来实现的。

// 销毁栈
void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_capacity = 0;
	ps->_top = 0;
}

这段代码实现了销毁栈的操作,具体实现如下:

首先,使用assert宏函数检查传入的栈指针ps是否为空,如果为空则程序终止。
释放栈空间,即使用free函数释放栈中元素所占用的空间。
将栈的空间指针_a置为NULL,表示栈已被销毁。
将栈的容量_capacity设为0,表示栈的容量已被清空。
将栈顶指针_top设为0,表示栈已经没有元素。
需要注意的是,这里的销毁栈操作是将栈空间释放掉,并将相应的成员变量值归0或置空,但并未释放栈结构体本身所占用的空间。如果需要彻底销毁栈,还需手动释放栈结构体所占用的空间。

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{
	STDataType* _a;
	int _top; // 栈顶
	int _capacity; // 容量
}Stack;
// 初始化栈
void StackInit(Stack* ps);
// 入栈
void StackPush(Stack* ps, STDataType data);
// 出栈
void StackPop(Stack* ps);
// 获取栈顶元素
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
bool StackEmpty(Stack* ps);
// 销毁栈
void StackDestroy(Stack* ps);
// 初始化栈
void StackInit(Stack* ps)
{
	assert(ps);
	ps->_a = (STDataType*)malloc(sizeof(STDataType)*4);
	if (ps->_a == NULL)
	{
		perror("malloc fail");
		return;
	}
	ps->_capacity = 4;
	ps->_top = 0;//top是栈顶元素的下一个位置
	//ps->_top = -1;//top是栈顶元素位置
}

// 入栈
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	if (ps->_top == ps->_capacity)
	{
		STDataType* tmp = (STDataType*)realloc(ps->_a,sizeof(STDataType) * ps->_capacity*2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		ps->_a = tmp;
		ps->_capacity *= 2;
	}
	ps->_a[ps->_top] = data;
	ps->_top++;
}

// 出栈
void StackPop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->_top--;
}
// 获取栈顶元素
STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->_a[ps->_top - 1];
}
// 获取栈中有效元素个数
int StackSize(Stack* ps)
{
	assert(ps);
	return ps->_top;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
bool StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->_top == 0;
}
// 销毁栈
void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_capacity = 0;
	ps->_top = 0;
}
int main()
{
	Stack st;
	StackInit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);
	StackPush(&st, 5);
	while(!StackEmpty(&st))
	{
		printf("%d ", StackTop(&st));
		StackPop(&st);
	}
	StackDestroy(&st);
	return 0;
}

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

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

相关文章

【软件架构】流水线设计模式

流水线模式 流水线模式是一种软件设计模式&#xff0c;它提供了构建和执行一系列操作的能力。 此模式最好与插件模式结合使用&#xff0c;以便在应用程序启动时动态构建流水线。 顺序 流水线的最基本实现是一个简单的操作序列。 public interface IOperation<T>{void …

【学习笔记】关于transformer

1.Embedding 一文读懂Embedding的概念&#xff0c;以及它和深度学习的关系 - 知乎 one-hot编码当矩阵过于稀疏时计算开销大&#xff0c;于是加上Embedding层&#xff0c;通过Embedding层&#xff08;矩阵乘法&#xff09;实现降维。 Embedding层将一个一个词&#xff08;词源…

Spring Boot 如何使用 Spring Security 进行认证和授权

Spring Boot 如何使用 Spring Security 进行认证和授权 在 Web 应用程序中&#xff0c;认证和授权是非常重要的功能。Spring Security 是一个基于 Spring 框架的强大的安全框架&#xff0c;它提供了完整的认证和授权解决方案&#xff0c;并且可以轻松地集成到 Spring Boot 应用…

gtk_table_attch与gtk_grid_attach的区别

gtk_table_attch与gtk_grid_attach的区别 button gtk_button_new_with_label (“Short fat button”); gtk_table_attach (GTK_TABLE (table), button, 0, 2, 3, 4, xoptions, yoptions, 0, 0); 0—2–3—4 左 右 上 下 /* 横线从左边的0移到右边的2&#xff0c;竖线从上边的…

3 python进阶篇

文章目录 面向对象类属性和类方法类属性类方法静态方法 单例模式__new__ 方法类实现单例模式 异常 、模块和包异常自定义异常 模块和包模块的搜索顺序包的init文件发布模块&#xff08;了解&#xff09; 文件seek文件/目录的常用管理操作eval函数 补充性知识位运算小技巧 参考我…

软考A计划-系统集成项目管理工程师-一般补充知识-中

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…

【LeetCode热题100】打卡第27天:二叉树的前序、中序、后序遍历

文章目录 【LeetCode热题100】打卡第27天&#xff1a;二叉树的前序、中序、后序遍历⛅前言&#x1f4d5;二叉树的前序遍历&#x1f512;题目&#x1f511;题解 &#x1f4d5;二叉树的中序遍历&#x1f512;题目&#x1f511;题解 &#x1f4d5;二叉树的后序遍历&#x1f512;题…

(万字长文)React 18 源码与原理解读 —— 看这一篇就够了

写在专栏开头&#xff08;叠甲&#xff09; 作者并不是前端技术专家&#xff0c;也只是一名喜欢学习新东西的前端技术小白&#xff0c;想要学习源码只是为了应付急转直下的前端行情和找工作的需要&#xff0c;这篇专栏是作者学习的过程中自己的思考和体会&#xff0c;也有很多参…

django中模板的使用

django中模板的使用 第一步 创建模板文件夹第二步 把模板存放进去第三步 把模板路径 加入到setting.py第四步 在视图函数处理第五步 路由挂载第六步 网页访问 第一步 创建模板文件夹 在项目的同层级下 新建模板文件夹 第二步 把模板存放进去 index.html <!DOCTYPE html&…

【Docker】一文了解Docker

文章目录 什么是Docker?为什么要使用Docker&#xff1f;与虚拟机的比较Docker架构Docker使用场景Docker安装阿里云镜像加速器1、登录阿里云2、找到镜像加速器3、配置使用 如今Docker的使用已经非常普遍&#xff0c;特别在一线互联网公司。使用Docker技术可以帮助企业快速水平扩…

C++ 自己动手实现简单的文件操作 (2023.6.23)

C 自己动手实现简单的文件操作 2023.6.23 引言1、文件简介2、各式各样的文件格式2.1 不同类型文件的扩展名2.1.1 文本文件2.1.2 数据文件2.1.3 音频文件2.1.4 视频文件2.1.5 电子书文件2.1.6 3D图像文件2.1.7 位图文件2.1.8 矢量图文件2.1.9 相机原始文件2.1.10 页面布局文件2.…

自监督对比学习框架SimCLR原理

目录 一、前言 人工智能发展近况 对比学习 二、数据集介绍 STL-10数据集 三、无监督图像表征对比学习 SimCLR SimCLR算法基本原理 数据增强与正负样本匹配 编码器 损失函数 对比学习全过程 四、有监督的图像下游任务迁移 替换下游任务网络层 有监督训练 五、实…

环境配置 | Git的安装及配置[图文详情]

Git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从小到大的项目版本管理。下面介绍了基础概念及详细的用图文形式介绍一下git安装过程. 目录 1.Git基础概念 2.Git的下载及安装 3.常见的git命令 Git高级技巧 Git与团队协作 1.Git基础概念 仓库&#…

Charm-Crypto在Anaconda虚拟环境下的安装教程--基于Ubuntu20.04

第零步 VMware虚拟机设置和安装Anaconda虚拟环境 因为后面要编译源码&#xff0c;所以最好把CPU设置为最大&#xff0c;例如我的电脑是4核8线程&#xff0c;则&#xff1a; 关于Anaconda虚拟环境&#xff0c;这里不再赘述&#xff0c;后面都假设已经安装好虚拟环境&#xff0c;…

包装类--Math 类--Arrays 类--System 类

包装类–Math 类–Arrays 类–System 类 包装类 包装类的分类 包装类和基本数据的转换 演示包装类和基本数据类型的相互转换&#xff0c;这里以int和Integer演示。 1&#xff09;jdk5前的手动装箱和拆箱方式&#xff0c;装箱&#xff1a;基本类型&#xff0d;>包装类型&…

OpenAI收费标准,ChatGPT调用须知!

OpenAI收费标准&#xff0c;ChatGPT调用须知&#xff01; 免费镜像站价格说明GPT4GPT3.5图片模型如何付费 免费镜像站 ChatGPT有很多镜像站&#xff0c;需要输入API-KEY才可以使用&#xff0c;镜像站不会进行收费&#xff0c;而是OpenAI会对您进行收费。本文主要说明OpenAI的收…

【好书精读】网络是怎样连接的 —— IP 与以太网的包收发操作

&#xff08; 该图由AI制作 &#xff09; 目录 包的基本知识 包收发操作概览 生成包含接收方 IP 地址的 IP 头部 生成以太网用的 MAC 头部 通过 ARP 查询目标路由器的 MAC 地址 以太网的基本知识 将 IP 包转换成电或光信号发送出去 给网络包再加 3 个控制数据 向集线…

代码随想录算法训练营第四十一天 | 背包问题(一维、二维)、416. 分割等和子集

01背包&#xff1a;n种物品&#xff0c;每种物品只有1个&#xff0c;有相应的重量和价值 最多只能装m的重量&#xff0c;最多价值为多少&#xff1f; dp[i][j] : [0, i]物品任取放进容量为j的背包里 不放物品i&#xff1a;dp[i-1][j] 放物品i&#xff1a;dp[i-1][j-weight[…

如何系统性的学习Python语言

零基础同学的福音来了&#xff0c;如果你对Python语言的学习感兴趣&#xff0c;接下来可以由浅入深的了解下Python语言&#xff0c;哪怕你是零基础的小白也完全可以学会的&#xff0c;最后也会给大家放出学习和实例相结合的教程及方法&#xff0c;给到各位同学系统性的教学&…

ES-索引管理

前言 数据类型 ​ 搜索引擎是对数据的检索&#xff0c;所以我们先从生活中的数据说起。我们生活中的数据总体分为两种&#xff1a; 结构化数据非结构化数据 结构化数据&#xff1a; 也称作行数据&#xff0c;是由二维表结构来逻辑表达和实现的数据&#xff0c;严格地遵循数…