什么是栈,为什么函数式编程语言都离不开栈?

news2024/11/24 15:22:26

文章目录

  • 一、什么是栈,什么是FILO
  • 二、栈的作用是什么,为什么编程语言函数调用都选择用栈?
  • 三、使用C模拟实现解析栈
    • 1.结构体的定义
    • 2.栈的创建及销毁
    • 3.实现入栈操作
    • 4.获取栈顶元素及出栈操作
    • 5.获取栈中有效元素个数
  • 源代码分享


一、什么是栈,什么是FILO

​ 栈是一种具有特殊访问方式的存储空间,它的特殊性在于,最后进入这个空间的数据,最先出去,可以画图来描述一下这种操作方式。

假设有一个盒子和三本书,依次将三本书他们放入盒子中。

入栈模拟图

在这里插入图片描述

​ 现在有一个问题,如果一次只能取一本,我们如何将书从盒子中取出来?

​ 显然必须从盒子的最上边开始取,依次取出,和放入的顺序刚好相反。

出栈模拟图

在这里插入图片描述

​ 从程序化的角度来讲,应该有一个标记,这个标记一直指示着盒子最上边的书。

​ 如果说,上图中的盒子就是一个栈,我们可以看出栈的两个基本操作:入栈和出栈。入栈就是将一个新元素放到栈顶,出栈就是从栈顶取出一个元素,栈顶的元素总是最后入栈,需要出栈时,有最先被从栈中取出。栈的这种操作被称为:LIFO(last in first out),后进先出

二、栈的作用是什么,为什么编程语言函数调用都选择用栈?

​ 为何现如今所有的编程语言都会采用栈来进行函数调用?函数调用的状态之所以用栈来记录是因为这些数据的存活时间满足“先进后出”(FILO)顺序,而栈的基本操作正好就是支持这种顺序访问的。下面用一组程序举例。

void test1(){}

void test2() {
	test1();
}

void test3() {
	test2();
}

int main() {
	test3();
}

这个程序运行的顺序为:main() ——》 test3() ——》 test2() ——》 test1() ——》 return from test1() ——》 return from test2() ——》 return from test3() ——》 return from test4().

​ 可以看到,调用者的生命周期总是长于被调用者的生命周期,并且后者在前者之内。被调用者的数据总是后于调用者的,而其释放顺序总是先于调用者,所以正好可以满足LIFO顺序,选用栈这种数据结构来实现函数调用则是一种自然而然的选择。

在这里插入图片描述

三、使用C模拟实现解析栈

​ 前面说过栈的两个基本操作,入栈和出栈,都只是对栈顶进行操作,栈可以用数组实现也可以用链表实现,这里讲解用数组实现,因为数组实现相对来说更优一些,数组实现在尾部插入数据代价比较小。

1.结构体的定义

​ 由于各种操作都只在栈顶进行,选择定义一个top来记录栈顶的位置,为了节省空间选择定义一个capacity来记录最大长度,如果等于top的话进行扩容。

typedef int STDataType;
typedef struct StackNode {
	STDataType* arr;
	int capacity;
	int top;
}STNode;

2.栈的创建及销毁

​ 由于函数内有对参数指针的引用,加上assert预防程序崩溃,易于调试,top初始化为-1(也可以初始化为0,个人偏向初始化为-1),两者的区别就是一个是栈顶指向栈顶数据,一个指向栈顶数据的下一个,其实本质上差不多。

void STInit(STNode* pst)
{
	assert(pst);
	pst->arr = NULL;
	pst->capacity = 0;
	pst->top = -1;
}

void STDestroy(STNode* pst)
{
	assert(pst);
	free(pst->arr);
	pst->arr = NULL;
	pst->capacity = 0;
	pst->top = 0;
}

3.实现入栈操作

​ 如果栈已经满了,则进行扩容,将数据放到栈顶

void STPush(STNode* pst,STDataType x)
{
	assert(pst);
	if (pst->capacity==pst->top+1)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* temp = NULL;
		temp = (STDataType*)realloc(pst->arr,sizeof(STDataType) * newcapacity);
		if (temp == NULL)
		{
			perror("malloc error");
			return;
		}
		pst->arr = temp;
		pst->capacity = newcapacity;
	}
	pst->arr[++pst->top] = x;
}

4.获取栈顶元素及出栈操作

​ 出栈操作将栈顶元素向下移动即可,甚至无需删除数据,因为再次进行入栈会将其覆盖掉。获取栈顶元素要获取top的下一个位置,因为top是先存后加

bool STEmpty(STNode* pst)
{
	return pst->top == -1;
}

void STPop(STNode* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	pst->top--;
}

STDataType STTop(STNode* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	return pst->arr[pst->top];
}

5.获取栈中有效元素个数

由于数组偏移度是从0开始存数据,所以指向栈顶的top比实际上个数要少1,真正有效元素个数要将top+1。

int StackSize(STNode* pst)
{
	assert(pst);
	return pst->top+1;
}

源代码分享

//stack.h
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int STDataType;
typedef struct StackNode {
	STDataType* arr;
	int capacity;
	int top;
}STNode;


void STInit(STNode* pst);
void STPush(STNode* pst,STDataType);
void STPop(STNode* pst);
void STDestroy(STNode* pst);
bool STEmpty(STNode* pst);
STDataType STTop(STNode* pst);
//stack.c
#include "stack.h"


bool STEmpty(STNode* pst)
{
	return pst->top == -1;
}



void STInit(STNode* pst)
{
	assert(pst);
	pst->arr = NULL;
	pst->capacity = 0;
	pst->top = -1;
}

void STDestroy(STNode* pst)
{
	assert(pst);
	free(pst->arr);
	pst->arr = NULL;
	pst->capacity = 0;
	pst->top = 0;
}

void STPush(STNode* pst,STDataType x)
{
	assert(pst);
	if (pst->capacity==pst->top+1)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* temp = NULL;
		temp = (STDataType*)realloc(pst->arr,sizeof(STDataType) * newcapacity);
		if (temp == NULL)
		{
			perror("malloc error");
			return;
		}
		pst->arr = temp;
		pst->capacity = newcapacity;
	}
	pst->arr[++pst->top] = x;
}

void STPop(STNode* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	pst->top--;
}

STDataType STTop(STNode* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	return pst->arr[pst->top];
}

int StackSize(STNode* pst)
{
	assert(pst);
	return pst->top+1;
}

//test.c
#include "stack.h"

void test1()
{
	STNode ST;
	STInit(&ST);
	STPush(&ST, 1);
	STPush(&ST, 2);
	STPush(&ST, 3);
	STPush(&ST, 4);
	STPush(&ST, 5);
	STPush(&ST, 6);
	STPush(&ST, 7);
	while (!STEmpty(&ST))
	{
		printf("%d ", STTop(&ST));
		STPop(&ST);
	}
	STDestroy(&ST);
}


int main()
{
	test1();
}

img

✨本文收录于数据结构理解与实现

下几期会继续带来栈的练习题以及与栈刚好相反的堆(FIFO)。如果文章对你有帮助记得点赞收藏关注。

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

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

相关文章

临时被拉去已经在进行中的项目组「救火」,该怎么开展管理?

当你被临时拉去参与正在进行中的项目组&#xff0c;需要进行所谓的「救火」工作时&#xff0c;你需要注意的是如何开展管理&#xff0c;以确保项目能够成功完成。 首先&#xff0c;你需要了解项目的当前状态。了解项目的进展情况、目标和计划&#xff0c;以及团队成员的角色和…

Vmware Linux磁盘空间扩容

Linux磁盘空间扩容 VMware虚拟机中配置&#xff08;1&#xff09;进入虚拟机设置界面&#xff0c;选择扩展磁盘容量。&#xff08;2&#xff09; 本次是在原来30G的基础上扩展为50G。 Linux中设置&#xff08;1&#xff09; 可以看出sda3是根分区&#xff0c;下面按照博客提示&…

栈的实现(附含经典例题)

&#x1f349;博客主页&#xff1a;阿博历练记 &#x1f4d6;文章专栏&#xff1a;数据结构与算法 &#x1f68d;代码仓库&#xff1a;阿博编程日记 &#x1f365;欢迎关注&#xff1a;欢迎友友们点赞收藏关注哦&#x1f339; 文章目录 &#x1f340;前言&#x1f3c4;‍♂️数…

Redis系列--哨兵模式

一、什么是哨兵 Redis Sentinel&#xff08;哨兵&#xff09;是一个分布式系统,你可以在一个架构中运行多个哨兵(sentinel) 进程, 这些进程使用 gossip协议(基于流行病传播方式的节点或者进程之间信息交换的协议&#xff0c;在分布式系统中被广泛使用) 来接收关于Master是否下线…

MySQL5.0完全卸载教程

一、停止MySQL服务 在系统服务中找到mysql服务并停止即可。 二、卸载mysql应用程序 在控制面板中卸载mysql应用程序 三、删除mysql文件夹 找到mysql一开始安装路径的文件夹&#xff0c;然后删除掉该整个文件夹。 四、删除注册表 &#xff08;1&#xff09;按winR键&#xff0c;…

架构师日记-从代码到设计的性能优化指南 | 京东云技术团队

一 前言 服务性能是指服务在特定条件下的响应速度、吞吐量和资源利用率等方面的表现。据统计&#xff0c;性能优化方面的精力投入&#xff0c;通常占软件开发周期的10%到25%左右&#xff0c;当然这和应用的性质和规模有关。性能对提高用户体验&#xff0c;保证系统可靠性&…

Java经典笔试题—day10

Java经典笔试题—day10 &#x1f50e;选择题&#x1f50e;编程题&#x1f95d;井字棋&#x1f95d;密码强度等级 &#x1f50e;结尾 &#x1f50e;选择题 (1)下列运算符合法的是&#xff08; &#xff09; A.&& B.<> C.if D.: A B. 泛型的标志, 例如 <T>…

【iOS】—— AFNetworking源码学习

AFNetworking 文章目录 AFNetworkingAFHTTPSessionManager *sessionManager [AFHTTPSessionManager manager];请求过程1、调用请求序列化类中的requestWithMethod方法进行序列化处理2、调用dataTaskWithRequest来生成一个datatask任务 AFURLSessionMangerAFHTTPSessionManagerU…

Linux服务器--基线检查

Linux服务器--基线检查 一、前言二、口令策略2.1 检查项—密码策略2.2 检查项—密码生存期2.3 检查项—检查密码生存期是否作用于每个用户 三、账号管理3.1 检查项—禁止存在UID相同的用户3.1 检查项—禁止存在空密码的帐户 四、认证授权4.1 检查项—登陆失败处理 五、文件权限…

Pytroch 模型权重初始化

目录 1 概念 2 权值初始化方法 2.1 常数初始化 2.2 均匀分布初始化 2.3 正态分布初始化 2.4 Xavier 均匀分布 2.5 Xavier 正态分布 2.6 kaiming 均匀分布 2.7 kaiming 正态分布 2.8 单位矩阵初始化 2.9 正交初始化 2.10 稀疏初始化 2.11 狄拉克δ函数初始化 3 py…

STC15通过内部BandGap电压值测量ADC外部输入电压

STC15通过内部BandGap参考电压值测量ADC通道外部输入电压 📜内部 BandGap参考电压值获取方式: 🎬通过VOFA图形化显示ADC值 🔧vofa+工具下载地址:https://www.vofa.plus/🌿验证对象:IAP15F2K61S2🌿时钟频率:11.0592MHz🌿波特率:115200🔖在通过STC-ISP烧录程序…

XSS攻击以及java应对措施

文章目录 一. XSS攻击介绍1. 前端安全2. xss攻击简介3. xss的攻击方式 二. java应对xss攻击的解决方案1. 强制修改html敏感标签内容2. 利用过滤器过滤非法html标签 一. XSS攻击介绍 1. 前端安全 随着互联网的高速发展&#xff0c;信息安全问题已经成为企业最为关注的焦点之一…

大脑的故事

婴⼉的神经元是相互独⽴的、未连接的。在⼈⽣的头两年&#xff0c; 随着⼤脑细胞接收感觉信息&#xff0c;它们异常迅速地连接起来。 每⼀秒就有多达 200万个新连接&#xff08;突触&#xff09;在婴⼉的⼤脑⾥形成。两岁时&#xff0c;⼩孩⼦拥有超过 100万亿个突触&#xff…

版本发布 | 科东软件Intewell-Win V2.1.0 release版本正式发布

Intewell是由科东软件自主研发的工业嵌入式实时操作系统&#xff0c;具有高实时&#xff0c;确定性、高安全、高可靠、虚拟化等特点。Intewell系统源自于1990年诞生的“道”操作系统&#xff0c;至今已有30多年历史&#xff0c;已在多种严苛环境下运行检验&#xff0c;广泛商用…

springboot+java超市收银管理系统idea

考虑到实际生活中在超市 POS 收银管理方面的需要以及对该系统认真的分析&#xff0c;将系统权限按管理员和员工这两类涉及用户划分。 Spring Boot 是 Spring 家族中的一个全新的框架&#xff0c;它用来简化Spring应用程序的创建和开发过程。也可以说 Spring Boot 能简化我们之…

mmFormer:用于脑肿瘤分割的不完全多模态学习的多模态医学Transformer

文章目录 mmFormer: Multimodal Medical Transformer for Incomplete Multimodal Learning of Brain Tumor Segmentation摘要本文方法Hybrid Modality-Specific EncoderModality-Correlated EncoderConvolutional DecoderAuxiliary Regularizer 实验结果 mmFormer: Multimodal …

Kali-linux使用假冒令牌

使用假冒令牌可以假冒一个网络中的另一个用户进行各种操作&#xff0c;如提升用户权限、创建用户和组等。令牌包括登录会话的安全信息&#xff0c;如用户身份识别、用户组和用户权限。当一个用户登录Windows系统时&#xff0c;它被给定一个访问令牌作为它认证会话的一部分。例如…

师从英国两院院士|生物医学科研人员获CSC资助赴剑桥大学访学

L老师拟申报CSC公派访问学者项目&#xff0c;希望到欧洲TOP学校&#xff0c;师从知名教授&#xff0c;在自己的研究基础上取得进一步的进展和突破。最终我们获得世界名校剑桥大学的邀请函&#xff0c;导师是英国皇家科学学会及英国医学科学院两院院士&#xff0c;凭借这份硬气十…

【SAP Abap】X-DOC:SE18/19 - SAP第四代增强概念理解

【SAP Abap】X-DOC&#xff1a;SE18/19 - SAP第四代增强概念理解 1、Tcode2、概念3、增强选项类型4、增强实现类型5、增强操作方式6、增强选项与增强实现关系7、增强实施建议 1、Tcode SE18&#xff1a;Business Add-Ins: Definitions&#xff08;增强点定义/查看&#xff09;…

云平台电子班牌系统源码

越来越多的教育单位加入了数字化校园和智慧校园建设行列。在不断探究、建设和实施的过程中&#xff0c;建立强大的、高扩展性的智慧教育管理平台被众多学校和教育单位所认同。智慧班牌是电子班牌信息发布系统的数据呈现端&#xff0c;也是智慧平台数据的采集工具之一。通过智慧…