数据结构——栈(Stack)

目录

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.mfbz.cn/a/299910.html

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

相关文章

Kafka_02_Producer详解

Kafka_02_Producer详解 ProducerProducerRecordSend&Close实现原理ProducerInterceptorSerializerPartitioner 事务 Producer Producer(生产者): 生产并发送消息到Broker(推送) Producer是多线程安全的(建议通过池化以提高性能)Producer实例后可发送多条消息(可对应多个P…

组合数据(Python实现)

一、主要目的: 1.熟悉组合数据的类型。 2.掌握列表、元组、字典、集合等组合数据的创建、访问方法。 3.掌握组合数据推导式的使用方法 4.熟悉组合数据的常见应用。 二、主要内容和结果展示: 1. 使用两…

OpenCV中实现图像旋转的方法

OpenCV中实现图像旋转的方法 函数:cv2.flip() 功能:水平或者垂直翻转 格式:dst cv2.flip(src,flipCode[,dst]) 参数说明: src:输入图像 dst:和原图像具有相同大小、类型的目标图像。 flipCode&#…

Python小细节之Gui图形化界面库的对比和选择(一分钟版)

引言 我想要把打包的python程序变得好看 交互起来变得简单 遂 图形化界面 然 相关的库有很多 所以 对比! 开整 8个图形化界面库 在Python中,有多种图形用户界面(GUI)库可以用来创建丰富的图形化应用程序。以下是一些主要的图…

竞赛练一练 第23期:NOC大赛每日一练,python题目刷题第8天,包含答案解析

题目来自:NOC 大赛创客智慧编程赛项Python 复赛模拟题(二) NOC大赛创客智慧编程赛项Python 复赛模拟题(二) 第一题: 编写一个成绩评价系统,当输入语文、数学和英语三门课程成绩时,输出三门课程总成绩及其等级。 (1)程序提示用户输入三个数字,数字分别表示语文、数学、…

3.1 数据链路层概述

目录 3.1 数据链路层概述3.1.1 关于数据链路层什么是数据链路从协议栈看数据链路层数据链路层信道类型 3.1.2 三个基本问题封装成帧透明传输差错控制循环冗余检验CRC(Cyclic Redundancy Check)原理 3.1 数据链路层概述 3.1.1 关于数据链路层 什么是数据…

odoo17 | 模型视图继承

前言 Odoo的强大之处在于它的模块化。模块专门用于满足业务需求,但模块也可以彼此交互。这对于扩展现有模块的功能非常有用。例如,在我们的房地产场景中,我们希望在常规用户视图中直接显示销售人员的属性列表。 但是在讨论特定的Odoo模块继…

HackTheBox - Medium - Linux - UpDown

UpDown UpDown 是一台中等难度的 Linux 机器,暴露了 SSH 和 Apache 服务器。在Apache服务器上,有一个Web应用程序,允许用户检查网页是否已启动。服务器上标识了一个名为“.git”的目录,可以下载以显示目标上运行的“dev”子域的源…

GA算法简介

GA算法简介 前言一、GA是什么二、GA简介1.思想2.流程3.过程 前言 今天学习一下优化中非常出名的遗传(GA)算法 ,它的起源可是来自达尔文的生物进化论。 一、GA是什么 百科定义:遗传算法(Genetic Algorithm,GA)最早是…

Java多线程技术11——ThreadPoolExecutor类的使用1-备份

1 概述 ThreadPoolExecutor类可以非常方便的创建线程池对象,而不需要程序员设计大量的new实例化Thread相关的代码。 2 队列LinkedBlockingQueue的使用 public class Test1 {public static void main(String[] args) {LinkedBlockingQueue queue new LinkedBlocki…

四则运算 C语言xdoj20

问题描述: 输入两个整数和一个四则运算符,根据运算符计算并输出其运算结果(和、差、积、商、余之一)。注意做整除及求余运算时,除数不能为零。 输入说明: 使用scanf()函数输入两个整数和一个运算符&#xf…

【好书推荐】深入理解现代JavaScript

目录 推荐理由内容简介本书阅读对象为什么推荐这本书,看大佬们怎么说总结 T. J. Crowder是一位拥有30年经验的软件工程师。在他的整个职业生涯中,他至少有一半时间是在使用JavaScript从事开发工作。他经营着软件承包和产品公司Farsight Software。他经常…

工业协议转换网关:打破通信壁垒,实现设备互联

在工业自动化领域,各种设备和系统间的通信协议不尽相同,这给不同设备间的集成和数据交互带来了挑战。工业协议转换网关作为一种解决这一问题的关键设备,能够实现不同协议间的转换和数据传输,打破通信壁垒,提高设备的协…

2.8 EXERCISES

如果我们想使用每个线程来计算向量加法的一个输出元素,那么将线程/块索引映射到数据索引的表达式是什么? 答:C 假设我们想用每个线程来计算向量加法的两个(相邻)元素。将线程/块索引映射到i(由线程处理的…

SpringSecurity集成JWT实现后端认证授权保姆级教程-数据准备篇

🍁 作者:知识浅谈,CSDN签约讲师,CSDN博客专家,华为云云享专家,阿里云专家博主 📌 擅长领域:全栈工程师、爬虫、ACM算法 💒 公众号:知识浅谈 🔥网站…

进阶学习——Linux系统安全及应用

目录 一、系统安全加固 1.账号安全基本措施 1.1系统账号清理 1.1.1延伸 1.2密码安全控制 1.3命令历史限制 1.4终端自动注销 二、使用su命令切换用户 1.用途及用法 2.密码验证 3.限制使用su命令的用户 4.查看su操作记录 5.sudo(superuse do)…

Linux下QT生成的(.o)、(.a)、(.so)、(.so.1)、(.so.1.0)、(.so.1.0.0)之间的区别

记录一下遇到的问题:Linux系统下Qt编译第三方动态库会生成多个.so文件,不了解的小伙伴可能很疑惑: (1)Linux 下 QT 生成的(.o)、(.a)和(.so)三个文…

如何向嵌入式设备中添加tcpdump工具

说明:tcpdump是一个在网络设备调试中一个非常重要的工具,它并不像hexdump等工具集成在busybox里面,也不像其他的软件一样只需要依赖linux标准的库就可以实现,它需要pcap相关的库和加密的相关库。 本文主要是基于realtek 83系列的…

APPnium 自动化实践 :第一步adb 连接手机

1. 下载安装 adb ,添加到环境变量。 ADB Download - Get the latest version of ADB and fastboot 2. 手机开启开发者模式 https://developer.huawei.com/consumer/cn/doc/quickApp-Guides/quickapp-open-developer-option-0000001137005543 3. adb 连接设备 【And…

网络安全与IP地址:构建数字世界的前沿堡垒

网络安全是当今数字社会中不可忽视的挑战之一。而IP地址,作为互联网通信的基础协议,既是数字化时代的桥梁,也是网络安全的关键节点。本文将剖析IP地址在网络安全领域的作用,以及如何利用其特性建立有效的网络安全策略。 IP地址&a…