栈的讲解及实现(图解+代码/C语言)

2023-11-19

今天为大家分享的是栈的模拟实现,本文主要讲解如何以数组的形式模拟实现,同时给出链表模拟实现栈的代码。
在这里插入图片描述

目录

图解栈的结构

对于栈,我们可以用八个字简要概括“先入后出,后入先出”。""就像一个木桶,最先放进去的被后放进去的压住,想要拿出就必须先把顶上的拿出。
在这里插入图片描述

数组模拟栈的分步实现

理解之后就很好实现了,下面让我们来实现“”的各个步骤吧。

创建并初始化

我们定义一个栈,需要用数组来模拟,也就需要记录下数组的头指针,还需要确定栈的容量和当前存储量,为此需要两个int类型的变量来记录栈顶位置和栈的容量大小。

typedef int STDataType;
typedef struct Stack
{
	STDataType* _a;
	int _top;		// 栈顶
	int _capacity;  // 容量 
}Stack;

// 初始化栈 
void StackInit(Stack* ps)
{
	assert(ps);
	ps->_a = NULL;
	ps->_capacity = ps->_top = 0;
}

入栈

入栈的过程就是将新的元素放到栈的最顶端,然后移动栈顶元素,即改变记录的栈顶元素下标。不过在入栈之前,需要注意的一点是检查栈是否还有剩余空间,如果没有就需要扩容
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

// 入栈 
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	if (ps->_capacity == ps->_top)
	{
		ps->_capacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;
		ps->_a = (STDataType*)realloc(ps->_a, ps->_capacity * sizeof(STDataType));
		assert(ps->_a);
	}
	ps->_a[ps->_top] = data;
	ps->_top++;
}

检测栈是否为空

在出栈的时候,需要注意下当我们栈内已经没有元素的时候,就无法继续元素出栈了。

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

出栈

出栈并不需要移除栈顶元素(下图一),我们只需要改变记录的栈顶元素下标即可(下图二)。同时不要忘记判断栈是否为空。
在这里插入图片描述
在这里插入图片描述

// 出栈 
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;
}

销毁栈

销毁栈的时候需要注意,不要忘记将数组的指针置为空哦。

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

链表模拟实现栈

模拟思路

运用链表我们也需要完成“先入后出,后入先出”,这就表示我们记录的指针必须一直指向最新入栈的结点,同时这个结点出栈之后,下一个结点必须是前一个入栈的结点,于是便可以利用头插法的单链表来模拟实现栈。下面可以对比一下数组(图一)和链表(图二)分别模拟实现栈的具体结构。
在这里插入图片描述
在这里插入图片描述

总体代码(函数名同数组模拟栈)

#include<iostream>
#include<stdio.h>
#include<malloc.h>
#include<assert.h>
typedef int STDataType;
typedef struct node
{
	STDataType x;
	struct node* next;
}node;
typedef struct Stack
{
	node* head;
	int nums;		// 长度
}Stack;

// 初始化栈 
void StackInit(Stack* ps)
{
	assert(ps);
	ps->head = NULL;
	ps->nums = 0;
}

// 入栈 
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	node* new_node = (node*)malloc(sizeof(node));
	new_node->x = data;
	new_node->next = ps->head;
	ps->head = new_node;
	ps->nums++;
}

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

// 出栈 
void StackPop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	node* del = ps->head;
	ps->head = ps->head->next;
	free(del);
	ps->nums--;
}

// 获取栈顶元素 
STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->head->x;
}

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

// 销毁栈 
void StackDestroy(Stack* ps)
{
	assert(ps);
	node* tmp = ps->head;
	while (tmp)
	{
		ps->head = ps->head->next;
		free(tmp);
		tmp = ps->head;
	}
	ps->head = NULL;
	ps->nums = 0;
}

int main()
{
	Stack sta;
	StackInit(&sta);
	StackPush(&sta, 1);
	StackPush(&sta, 2);
	StackPush(&sta, 3);
	StackPush(&sta, 4);
	StackPush(&sta, 5);
	std::cout << StackSize(&sta) << std::endl;
	while (!StackEmpty(&sta))
	{
		printf("%d", StackTop(&sta));
		StackPop(&sta);
	}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

栈的讲解及实现(图解+代码/C语言) 的相关文章

  • 多个线程调用同一个函数

    假设我们有多个线程都调用同一个函数 def foo do stuff end 100 times do i Thread new do foo end end 如果当前有两个或多个线程foo 它们是否共享相同的局部变量foo 这涉及到我的第
  • 华为OD机试真题-围棋的气-2023年OD统一考试(C卷)

    题目描述 围棋棋盘由纵横各19条线垂直相交组成 棋盘上一共19x19 361个交点 对弈双方一方执白棋 一方执黑棋 落子时只能将棋子置于交点上 气 是围棋中很重要的一个概念 某个棋子有几口气 是指其上下左右方向四个相邻的交叉点中 有几个交叉
  • 牛客字符串

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 例如 随着人工智能的不断发展 机器学习这门
  • “调用堆栈”和“线程堆栈”之间的区别

    术语之间是否存在语义差异call stack and thread stack 在Java多线程中 每个线程都有自己的调用堆栈 调用堆栈 和 线程堆栈 是同一个东西 称其为 线程堆栈 只是强调调用堆栈是特定于线程的 Bill Venners
  • 排序:计数排序

    一 概念 计数排序是非比较排序 是对哈希直接定址法的变形应用 二 思想 利用数组统计相同数据出现的次数 例如整型数据m出现n次 就在数组m位置记录数据为n 最后从头遍历数组打印数据即可 通俗来讲就是 数组下标即为数据 下标所指位置的值即为数
  • 华为OD机试真题-整数对最小和-Java-OD统一考试(C卷)

    题目描述 给定两个整数数组array1 array2 数组元素按升序排列 假设从array1 array2中分别取出一个元素可构成一对元素 现在需要取出k对元素 并对取出的所有元素求和 计算和的最小值 注意 两对元素如果对应于array1
  • 单向不带头链表的使用

    单向不带头链表的使用 链表的创建 typedef struct LNode SLDataType data struct LNode next LNode LinkList 按位查找 LNode GetElem LinkList L int
  • 顺序表和链表基础

    定义动态的顺序表 typedef int SLDataType typedef struct Seqlist SLDataType array size t size size t capacity Seqlist 在顺序表中插入数据 bo
  • 用栈实现队列(OJ中报错的处理)

    用栈实现队列 ERROR AddressSanitizer myQueueFree函数中栈的释放处现了问题 没有调用StackDestory而是直接free了 这个是栈初始化时 capacity与malloc申请的空间大小没有匹配 请你仅使
  • 高精度运算合集,加减乘除,快速幂,详细代码,OJ链接

    文章目录 零 前言 一 加法 高精度加法步骤 P1601 A B 二 减法 高精度减法步骤
  • 最大流-Dinic算法,原理详解,四大优化,详细代码

    文章目录 零 前言 一 概念回顾 可略过 1 1流网络 1 2流 1 3最大流 1 4残留网络 1 5增广路
  • 运行时检查失败 #2 - 变量“x”周围的堆栈已损坏

    在以下代码中返回时 我收到此运行时检查失败 我相信类似的代码在程序的其他地方运行良好 有任何想法吗 String GetVariableName CString symbol CString filepath char acLine 512
  • 裸机环境下malloc什么时候返回NULL?

    有一个c内存模型如下 Last Address of RAM Stack v RAM Heap ZI RW First Address of RAM 堆栈和堆空间以相反的方向增加 它们会在中间相互重叠
  • Excel VBA 的 LIFO(堆栈)算法/类

    我正在寻找在 Excel 的 VBA 中实现 Stack 类 我想使用后进先出结构 以前有人遇到过这个问题吗 你知道外部库处理结构 如 Stack Hastable Vector 除了原始的 Excel Collection 等 Thank
  • 我怎样才能看到我的delphi应用程序当前使用了多少堆栈空间?

    我怎样才能看到我的delphi应用程序当前使用了多少堆栈空间 我曾有一个very奇怪的错误听起来像是堆栈问题 我想将其添加到我的应用程序日志中 以了解正在使用 剩余的堆栈空间有多少 使用调试器可能不太好 因为可以多次调用例程 谢谢你 这应该
  • 在 D 中制作结构体的堆副本

    如何创建堆栈上结构的垃圾收集副本 来自 C 背景 我的第一个猜测是像下面这样的复制构造函数 但它对于 D 来说似乎不太惯用 而且我在我看过的任何 D 项目中都没有看到过这样的复制构造函数 struct Foo immutable int b
  • 在Java中,为什么Stack是一个具体类,而Queue是一个接口?

    Queue 的哪一个子类是 普通 队列 1 java util Stack 是 Java 1 0 的遗留类 它早于 Collections 框架很多年 坦率地说 它是一个例子horrible多方面的设计 一切都不是事情应有的样子 主要问题是
  • 增加 Windows 上的堆栈大小 (GCC)

    有没有办法在使用 GCC 编译 链接时增加 Windows 应用程序的堆栈大小 IIRC 在 GCC 中 您可以向 ld 提供 stack bytes 参数 E g gcc Wl stack 16777216 o file exe file
  • 在C语言中,我可以通过堆栈指针访问另一个函数中主函数的局部变量吗?

    我需要访问在 main 函数中定义的变量 a 的值 而不将其作为参数传递 main int a 10 func printf d n a void func i need access of variable a here 我怎样才能做到这
  • 有没有比使用 backtrace() 更便宜的方法来查找调用堆栈的深度?

    我的日志记录代码使用的返回值回溯 http linux die net man 3 backtrace确定当前堆栈深度 出于漂亮的打印目的 但我可以从分析中看到这是一个相当昂贵的调用 我不认为有更便宜的方法吗 请注意 我不关心帧地址 只关心

随机推荐

  • 制作及运行 WebUI(NovelAI)Docker 镜像

    准备 Novel AI 模型文件 下载地址 magnet xt urn btih 5bde442da86265b670a3e5ea3163afad2c6f8ecc 只需要部分下载其中的文件 必须的文件 文件 stableckpt anime
  • Node.js知识点详解(一)基础部分

    模块 Node js 提供了exports 和 require 两个对象 其中 exports 是模块公开的接口 require 用于从外部获取一个模块的接口 即所获取模块的 exports 对象 接下来我们就来创建hello js文件 代
  • AI圈最新深度学习量化算法!

    文章摘自AAAI21 译者 一元 量化交易和投资决策是复杂的金融任务 依赖于准确的股票选择 目前深度学习学习的策略使用于股票的问题的方案面临两个重大局限 他们不直接优化利润方面的投资目标 将每只股票视为独立于其他股票 忽略了相关股票之间的丰
  • SpringCloudGateway路由策略:Nacos同集群优先

    使用版本
  • Python sorted()

    最简单的用法 gt gt gt sorted 36 5 12 9 21 21 12 5 9 36 反向排序的 gt gt gt sorted 36 5 12 9 21 reverse True 36 9 5 12 21 更高级的用法 gt
  • win和linux下如何给Qt应用程序添加图标

    给程序添加图标 包含2个部分 第一个 是可执行文件的图标或桌面快捷方式图标 第二个 是程序运行时窗口的图标 分别如下 接下来 我们分别在windows和linux下 讲解如何设置这2种图标 一 在windows系统下 1 设置应用程序图标
  • kubernates k8s minikube 安装 及使用 CentOS 7

    参考文章 CentOS 7安装minikube 重点参考 https www cnblogs com harmful chan p 12731014 html Linux环境上安装MiniKube https blog csdn net u
  • Gitlab merge 时提示”Source branch does not exist”问题的一个解决方案

    背景 将 gitlab 从服务器上迁到阿里云主机 版本从 9 4 1 ce 0 升级到 11 4 3 ce 0 迁移前后均使用 docker 部署 在云主机上运行后 发现在本地推送新分支到 gitlab 并进行 merge 操作时 merg
  • (嵌入式开发)STM32 网站、开发工具使用、参考、数据手册下载不在求人

    目录 一 ST 常用资源网 1 1 ST 之数据手册与用户手册区别 1 2 如何搜索下载对应的芯片文档呢 二 CubeMX 的下载 2 1 如何下载CubeMX 相关软件 2 2 如何自己安装 2 3 CubeMX 资源包当中有什么 三 K
  • Pandas对Excel行和列进行操作

    获取行数据 filename 测试表 xlsx df pd DataFrame pd read excel filename df2 df df 状态 等待付款 df 状态 已提交 print df loc 6000 tolist 输出第6
  • laravel-admin 在指定的相册下添加照片

    相册与照片是一对多的关系 有以下需求 1 点开一条相册数据看到相册的照片列表 2 为相册添加照片时 表单中要看到相册的基本信息 以下是实现步骤 第一步 构建带参数路由 router gt resource manage albumid ph
  • 常用的chrome配置参数

    让chromedriver不打开网页在后台进行 如果对chrome的启动参数感兴趣可以去看看脑补连接 from selenium import webdriver chrome options webdriver ChromeOptions
  • 解决pycharm安装python第三方库时遇到的问题——pycharm实体环境与虚拟环境

    目录 关于cmd打开cd操作的提示 1 pycharm虚拟环境和本地环境有啥区别 2 实体环境和虚拟环境怎么安装库 3 如何查询实体环境安装的库和虚拟环境安装的库 4 怎么切换本地环境或虚拟环境 5 总结使用pycharm时常见的3中环境
  • Jenkins插件开发之环境构建

    1 环境 1 1 jdk 1 1 1 下载 Java Platform Standard Edition 8 ReferenceImplementations 或其他途径下载 1 1 2 java环境配置 1 1 2 1 右键此电脑 属性
  • 【Python】实用小脚本

    本文整理了我在学习和工作中用到的实用python脚本 希望也能帮助到需要的小伙伴 文章目录 视频格式转换 pip快速下载命令 多进程处理百万图片数据集 视频格式转换 安装视频处理库moviepy pip install moviepy 安装
  • 【程序员面试金典】请设计一个算法,求出a和b点的最近公共祖先的编号。

    题目描述 有一棵无穷大的满二叉树 其结点按根结点一层一层地从左往右依次编号 根结点编号为1 现在有两个结点a b 请设计一个算法 求出a和b点的最近公共祖先的编号 给定两个int a b 为给定结点的编号 请返回a和b的最近公共祖先的编号
  • JavaWeb servlet的使用

    在jsp文件中没有java代码我们才算是学完啦 从EL表达式和JSTL标签 在减少在login jsp和index jsp中的java代码 而今天的学习是让在jsp中彻底没有java代码 原本写在doLogin jsp做登录判断的java代
  • 图像检索传统算法学习笔记

    图像检索领域传统算法学习笔记 与组内同学一起找到的一些图像检索传统算法 作一小结 以防忘记 性能统计 传统图像检索算法 CIFAR 10数据集mAP值 编码数不同 LSH局部敏感哈希 0 116 0 131 SH谱哈希 0 124 0 12
  • PhotoShop 之钢笔工具

    钢笔工具如下如 1 绘制直线 若按住Shift 键 单击鼠标左键可以绘制90度或者45度直线 按住Ctrl 并在空白处 单击鼠标左键 可退出绘制模式 2 绘制曲线 绘制第一个点单击 绘制第二个点的时候 按住鼠标左键并拖动即可绘制曲线 若想绘
  • 栈的讲解及实现(图解+代码/C语言)

    今天为大家分享的是栈的模拟实现 本文主要讲解如何以数组的形式模拟实现 同时给出链表模拟实现栈的代码 目录 图解栈的结构 数组模拟栈的分步实现 创建并初始化 入栈 检测栈是否为空 出栈 获取栈顶元素 获取栈内有效元素个数 销毁栈 链表模拟实现