数据结构——栈(Stack)

news2024/9/27 15:24:04

目录

1.栈的介绍

2.栈工程

2.1 栈的定义

2.1.1 单链表实现栈

2.1.2 数组实现栈

2.1.2.1 静态数组栈

2.1.2.2 动态数组栈

2.2 栈的函数接口

2.2.1 栈的初始化

2.2.2 栈的数据插入(入栈)

2.2.3 栈的数据删除(出栈)

2.2.4 判断栈是否为空

2.2.5 取栈顶数据

2.2.6 栈数据统计

2.2.7 栈销毁

3. 栈总结反思


1.栈的介绍

        栈这个东西我们并不陌生,有过一些基础知识的同志都知道,在存储器映像中就有一块存储区域被称为栈。这个栈主要是存储非静态局部变量,函数调用所开辟出的栈帧也在这块区域。对于这块区域,我们很明确的一点就是它的特征:先进后出,后进先出。在程序运行时(以Linux+IA32为例),栈顶指针esp在面对push和pop指令时会对应的减或加,栈空间的开辟和释放都是由esp指针来标定的。所以可以看到在栈区内,当要完成空间释放或申请时,总是在对最顶部的空间进行操作,即满足“先进后出,后进先出”的规则。

        我们今天要介绍的栈则是一种数据结构,也属于线性表的一种,其重要特征就是我们刚才所提到的先进后出,后进先出。当数据存入时,会采取push(入栈/压栈)操作,将数据存储在栈顶;当数据删除时,会采取pop(出栈/弹栈)操作,将位于栈顶位置的数据删除。

2.栈工程

2.1 栈的定义

        在实现栈的时候,我们需要考虑数据存储的方式。我们到目前掌握的存储方式有如顺序表的数组的结构,除此之外,还有链表结构。在实现栈这一方面,链表和数组的方式存储都可以。但是考虑到我们在需要频繁地访问栈顶,我们需要对这两种方式有所规定。

2.1.1 单链表实现栈

        使用单链表的时候我们要规定好栈顶和栈底。因为对于栈这种数据结构,我们需要频繁地访问栈顶,但是对于单链表而言其数据的插入是将结点链接在链表末端。两相对比,我们发现使用单链表在入栈出栈的时候代价很大,需要遍历链表。所以我们一般不使用单链表来实现栈。

2.1.2 数组实现栈

        使用数组实现栈也同样需要先明确栈顶栈底的位置。因为栈顶是“灵活多变”的,栈顶会随着数据的插入和删除而更改位置。对于一个数组而言很明显下标大的一端更容易适应这样的特性,所以我们一般将下标为0的一端作为栈底,将下标较大的一端作为栈顶。

        在明确了数组的格式后,我们自然的想到动态的数组和静态的数组两种结构。

2.1.2.1 静态数组栈

        对于一个静态数组栈,其数组长度是定长的,我们定义一个常量来统一管理。其栈结构(结构体)中除了一个存储数据的定长数组之外,还应该有一个成员来标识栈顶的位置,便于我们对栈进行访问。

//静态
typedef int STDataType;
#define N 10
typedef struct Stack
{
 STDataType _a[N];
 int _top; // 栈顶
}Stack;
2.1.2.2 动态数组栈

        对于动态数组的栈来说,为满足其灵活管理空间的功能,其结构体内需要一个指针指向我们动态开辟的数组。同样的我们也需要一个成员标识栈顶位置,还需要一个成员存储数组容量上限。

typedef int STDataType;

typedef struct Stack
{
	STDataType* data;
	int top;
	int capacity;
}ST;

2.2 栈的函数接口

2.2.1 栈的初始化

        当新建一个栈后,我们需要对其结构体进行初始化。将指针值为空,将容量初始化为0,同时将表示栈顶的成员置为-1。top初始化为-1,表示栈顶所在元素下标,-1即为栈为空。也可以将top初始化为0,表示栈内元素个数。此处选择第一种方式。

void STInit(ST* pst)
{
	assert(pst);

	pst->data = NULL;
	pst->top = -1;
	pst->capacity = 0;
}

2.2.2 栈的数据插入(入栈)

        当要在栈中插入数据时,我们首先要判断是否需要扩容,从而防止越界访问的问题。修改完容量后只需要将数据存储到数组的末端(栈顶)即可。

void STPush(ST* pst,STDataType x)
{
	assert(pst);

	if (pst->top + 1 == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = realloc(pst->data, newcapacity*sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->data = tmp;
		pst->capacity = newcapacity;
	}
	pst->top++;
	pst->data[pst->top] = x;
}

2.2.3 栈的数据删除(出栈)

        出栈只需要将top减1即可,注意使用断言限制空指针与越界访问。

void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top != -1);

	pst->top--;
}

2.2.4 判断栈是否为空

        栈是否为空只需要判断top成员是否为-1即可。

bool STEmpty(ST* pst)
{
	assert(pst);

	return pst->top == -1;
}

2.2.5 取栈顶数据

        因为top保存的是栈顶的下标,所以取栈顶元素只需要访问该下标元素即可。

STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top != -1);

	return pst->data[pst->top];
}

2.2.6 栈数据统计

        该接口是为了输出此时栈内的数据个数,只需将栈顶下标加一即可。

int STSize(ST* pst)
{
	assert(pst);

	return pst->top + 1;
}

2.2.7 栈销毁

        销毁栈需要将其数组空间释放,并将结构体内成员值全部初始化。

void STDestroy(ST* pst)
{
	assert(pst);

	free(pst->data);
	pst->data = NULL;
	pst->capacity = 0;
	pst->top = -1;
}

3. 栈总结反思

        栈主要实现了“先进后出,后进先出”的特殊功能,这就意味着栈这种数据结构在面对一些满足该特性的一些特殊情况下才能很好的适配。其结构和实现并不复杂,相较于其他数据结构很容易理解,特征也非常明显,处理好一些类似于下标之类的小细节就没问题了。

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

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

相关文章

【docker】centos 使用 Nexus Repository 搭建私有仓库

Nexus Repository 是一种流行的软件仓库管理工具,它可以帮助您搭建私有仓库,以便在内部网络或私有云环境中存储、管理和分发各种软件包和组件。 它常被用于搭建Maven的镜像仓库。本文演示如何用Nexus Repository搭建docker 私有仓库。 使用Nexus Repos…

【InternLM】Lagent智能体工具调用实践浦语·灵笔(InternLM-XComposer)图文理解创作Demo练习

目录 前言一、Lagent智能体工具1-1、什么是智能体?1-2、Lagent智能体 二、InternLM-XComposer(图文理解创作模型介绍)三、Lagent调用实践3-0、环境搭建3-1、创建虚拟环境3-2、导入所需要的包3-3、模型下载3-4、Lagent安装3-5、demo运行 四、I…

阿里云服务器固定带宽下载和上传速度对照表

阿里云服务器公网带宽上传和下载速度对照表,1M带宽下载速度是128KB/秒,为什么不是1M/秒?阿腾云atengyun.com分享阿里云服务器带宽1M、2M、3M、5M、6M、10M、20M、30M、50M、100M及200M等公网带宽下载和上传速度对照表,附带宽价格表…

性能测试之(九):JMeter关联

关联:当请求之间有依赖关系,比如下一个请求的入参是上一个请求返回的数据,这需要进行关联处理; 关联场景1:登录之后返回token,后续的请求需要带token; 常用的关联方法:(在后置处理器…

[算法应用]dijkstra算法的应用

先看一眼原始dijkstra算法,参考自dijkstra算法C实现_c实现djikstra-CSDN博客 分为三步 找到当前最优的把当前最优的,不参与后面的更新逐个比较是否更新 dijkstra算法的应用 题目大概是要从图上找一条权值不减的路径,且要经过最多的点。 所以…

odoo17 | 模型之间的内联视图

前言 从商业角度来看,我们的房地产模块现在是有意义的。我们创建了特定的视图,添加了几个操作按钮和约束。然而,我们的用户界面仍然有点粗糙。我们想为列表视图添加一些颜色,并使一些字段和按钮有条件地消失。例如,当…

STM32F407ZGT6时钟源配置

1、26M外部时钟源 1、25M外部时钟源

四种方式实现[选择性注入SpringBoot接口的多实现类]

最近在项目中遇到两种情况,准备写个博客记录一下。 情况说明:Service层一个接口是否可以存在多个具体实现,此时应该如何调用Service(的具体实现)? 其实之前的项目中也遇到过这种情况,只不过我采…

【linux应用开发】进程通信总结——使用管道、消息队列、共享内存、信号量实现l进程通信的详细教程

文章目录 简介无名管道有名管道IPC key标识消息队列共享内存信号量 简介 进程间通信(IPC, Inter-Process Communication)是指在操作系统中,不同进程之间交换数据、信息和命令的过程。在一个多任务的操作系统中,多个进程可以同时运…

Python和Java环境搭建

小白搭建全流程 首先不建议装在C盘,一旦重置电脑,之前安装第三方包需要重新安装 relolver :解释器 1、Python解释器安装 资源包: 1、 python -version java -version–用于查看是否安装 where python whrer java–用于查看安装的位置【非常…

ARTrack 阅读记录

目录 环境配置与脚本编写 前向传播过程 网络结构 环境配置与脚本编写 按照官网执行并没有顺利完成,将yaml文件中的 pip 项 手动安装的 conda create -n artrack python3.9 # 启动该环境,并跳转到项目主目录路径下 astor0.8.1 configparser5.2.0 data…

(2023|NIPS,MUSE,掩蔽适配器,基于反馈的迭代训练)StyleDrop:任意风格的文本到图像生成

StyleDrop: Text-to-Image Generation in Any Style 公和众和号:EDPJ(添加 VX:CV_EDPJ 或直接进 Q 交流群:922230617 获取资料) 目录 0. 摘要 3. StyleDrop:文本到图像合成的风格调整 3.1 基础&#x…

Java-网络爬虫(二)

文章目录 前言一、WebMagic二、使用步骤1. 搭建 Maven 项目2. 引入依赖 三、入门案例四、核心对象&组件1. 核心对象SipderRequestSitePageResultItemsHtml(Selectable) 2. 四大组件DownloaderPageProcessorSchedulerPipeline 上篇:Java-网…

浅析Attention

本质: Attention机制的本质来自于人类视觉注意力机制。人们在看东西的时候一般不会从头看到尾全部都看,往往只会根据需求观察注意特定的一部分。简单来说,就是一种权重参数的分配机制,目标是协助模型捕捉重要信息。 原理&#x…

自监督深度学习技术

一、定义 自监督学习(SSL)是机器学习的一种范式,用于处理未标记数据以获取有用的表示,以帮助下游学习任务。SSL方法最显著的特点是它们不需要人类标注的标签,这意味着它的训练完全基于由未标记的数据样本组成的数据集…

在做题中学习(43):长度最小的子数组

LCR 008. 长度最小的子数组 - 力扣(LeetCode) 解法:同向双指针-------滑动窗口算法 解释:本是暴力枚举做法,因为全部是正整数,就可以利用单调性和双指针解决问题来节省时间 思路: 如上面图&am…

IIS+SDK+VS2010+SP1+SQL server2012全套工具包及安装教程

前言 今天花了两个半小时安装这一整套配置,这个文章的目标是将安装时间缩短到1个小时 正文 安装步骤如下: VS2010 —> service pack 1 —>SQL server2012 —> IIS —> SDK 工具包链接如下: https://pan.baidu.com/s/1WQD-KfiUW…

[Linux] 一文理解HTTPS协议:什么是HTTPS协议、HTTPS协议如何加密数据、什么是CA证书(数字证书)...

之前的文章中, 已经分析介绍过了HTTP协议. HTTP协议在网络中是以明文的形式传输的. 无论是GET还是POST方法都是不安全的. 为什么不安全呢? 因为: HTTP协议以明文的形式传输数据, 缺乏对信息的保护. 如果在网络中传输数据以明文的形式传输, 网络中的任何人都可以轻松的获取数据…

Java:File类详解

文章目录 1、概述2、创建File实例3、常用方法3.1 获取功能的方法3.2 绝对路径和相对路径3.3 判断功能的方法3.4 创建删除功能的方法3.5 文件过滤功能的方法 4、文件夹的遍历5、综合练习5.1 创建文件夹5.2 查找文件(不考虑子文件夹)5.3 查找文件&#xff…

RK3568平台开发系列讲解(Linux系统篇)Linux 内核打印

🚀返回总目录 文章目录 一、方法一:dmseg 命令二、方法二:查看 kmsg 文件三、方法三:调整内核打印等级一、方法一:dmseg 命令 在终端使用 dmseg 命令可以获取内核打印信息,该命令的具体使用方法如下所示: 首先在串口终端使用 “dmseg”命令,可以看见相应的内核打印信息…