数据结构篇其四---栈:后进先出的魔法世界

news2024/11/19 16:44:57

前言

栈的学习难度非常简单,前提是如果你学过顺序表和单链表的话,我直接说我的观点了,栈就是有限制的顺序表和单链表。

栈只允许一端进行插入删除。栈去除了各种情况复杂的插入删除,只允许一端插入删除的特性,这一种数据结构在实际应用场景非常有价值。

栈的概念

栈是一种线性表,其中只允许固定的一段进行插入删除元素操作。

其中进行数据插入和删除操作的一端称为栈顶;

另一端称为栈底。

栈中数据遵循一个元素LIFO(Last In Fast Out),后进先出原则。

栈有一句话概括了它的特点:先进后出,后进先出。

进栈与出栈一图流搞定。

栈的定义

栈分两种存储结构:

1.顺式存储结构,比如前面的顺序表。顺序表可以通过静态数组和动态数组实现。

那么栈的顺式存储结构也能通过静态数组和动态数组实现。这种栈称为数组栈。

2.链式存储结构,比如链表(这里指单链表)。栈也能像单链表那样的结构定义,这种栈称为链表栈。

数组栈(顺序栈)

数组有定长数组和动态数组。

选择数组下标为0为栈底,选择存储有效数据最远的为栈顶。

对于静态数组的栈,不妨我们称做静态(数组)栈。

要素

1.定长数组。

2.栈顶指针(用于记录当前位置)。

注意:栈顶指针不一定是真的指针,这里可以数数组下标,因为数组在内存中连续存储的特性,用下标也就是在用指针。

对于复杂数据类型,还是离不开结构体。如下:

#define NUM_MAX 100//看情况调整
typedef int STDataType;
typedef struct Stack
{
	STDataType arr[NUM_MAX];//定长数组
	int top;//栈顶指针
}ST;

tip:这里的top其实就是静态顺序表的size,只是换了一个变量名。

这里换成top其实是要养成良好的取名风格,方便后续的学习。 

 后面针对动态数组实现的栈,我们不妨称为动态(数组)栈

要素:

1.栈数据类型的一级指针;用于动态内存分配

2.栈顶指针;(前面解释过,不在解释)

3.容量大小;(动态数组不会记住当前已有的空间大小,需要额外引入变量记录)

总结:用结构体,和动态顺序表一模一样,除了size改了个名叫top。

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

链式栈  

首先选择什么类型链表结构,链表结构合计8种,由于进栈出栈限定在一端操作,单链表就适合。(栈不适合带头结点的单链表)

哪端作为栈顶,另一端作为栈底呢?

由于单链表的单向性且要符合栈的LIFO特性。

头指针指向处为栈顶,尾结点处为栈底。

typedef int STDataType;
typedef struct Stack
{
	struct Stack* next;
	STDataType data;
}ST;

您可能想问,这不就是单链表吗,跟链式栈有什么区别?

不不不,单链表还有一个关键的东西----头指针。

头指针和栈顶指针合二为一了。接下来只要用该结构体实现栈的相关函数,就可以明显区分单链表和链式栈的差别了。

ST* top = NULL;//创建一个链式栈

栈的实现(用动态数组栈实现)

数组栈比链式栈更简单,所以我们优先实现数组栈。

这里出栈进栈等价于顺序表的尾删和尾插,顺序表处理这方面效率是最高的。

显然用顺序栈(数组栈),前排提醒:实现顺序表可以说相当简单。

这里选择数组栈的动态数组的方式实现。



#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<assert.h>


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

//栈的初始化
void STInit(ST* pst);

//栈的销毁
void STDestroy(ST* pst);

//压栈/进栈/入栈
void STPush(ST* pst,STDataType x);

//出栈
void STPop(ST* pst);

//获取栈顶元素
STDataType STTop(ST* pst);

//判空
bool STEmpty(ST* pst);

//栈上合计多少个元素个数
int STsize(ST* pst);

 

栈的初始化

void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	//pst->top = -1;//top指向最新插入的数据

	//以这个为例
	pst->top = 0;//top指向当前有效数据的下一个位置。
	pst->capacity = 0;//容量大小

}

栈的销毁 

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

	free(pst->a);//释放动态开辟空间

	//以下同初始化
	pst->a = NULL;
	pst->top = pst->capacity = 0;//置空

}


压栈函数

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

	//动态增容
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;
		STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));//给动态数组开辟空间
		if (tmp == NULL)//判断空间是否开辟失败
		{
			perror("realloc fail");
			return;
		}

		pst->a = tmp;//开辟成功赋值
		pst->capacity = newcapacity;
	}
	pst->a[pst->top++] = x;
}

出栈函数

void STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));//空栈不能删除
	pst->top--;//直接改变栈顶即可
}

栈顶元素函数

STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));//空栈没有元素了
	return pst->a[pst->top-1];
}

判断空栈函数

bool STEmpty(ST* pst)
{
	assert(pst);
	return pst->top == 0;//判断是否为空栈
}


计算栈的长度

int STsize(ST* pst)
{
	assert(pst);
	return pst->top;//返回当前栈上的元素个数。
}

总源代码

请自行迁移用静态数组和单链表表示栈。

#include<stdio.h>
#include<stdbool.h>//bool类型
#include<stdlib.h>//realloc动态内存函数
#include<assert.h>//assert断言

//结构体声明定义
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

//栈的初始化
void STInit(ST* pst);

//栈的销毁
void STDestroy(ST* pst);

//压栈/进栈/入栈
void STPush(ST* pst, STDataType x);

//出栈
void STPop(ST* pst);

//获取栈顶元素
STDataType STTop(ST* pst);

//判空
bool STEmpty(ST* pst);

//栈上合计多少个元素个数
int STsize(ST* pst);


void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	//pst->top = -1;//top指向最新插入的数据

	//以这个为例
	pst->top = 0;//top指向当前有效数据的下一个位置。
	pst->capacity = 0;//容量大小

}

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

	free(pst->a);//释放动态开辟空间

	//以下同初始化
	pst->a = NULL;
	pst->top = pst->capacity = 0;//置空

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

	//动态增容
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;
		STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));//给动态数组开辟空间
		if (tmp == NULL)//判断空间是否开辟失败
		{
			perror("realloc fail");
			return;
		}

		pst->a = tmp;//开辟成功赋值
		pst->capacity = newcapacity;
	}
	pst->a[pst->top++] = x;
}

void STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));//空栈不能删除
	pst->top--;//直接改变栈顶即可
}

STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));//空栈没有元素了
	return pst->a[pst->top-1];
}

bool STEmpty(ST* pst)
{
	assert(pst);
	return pst->top == 0;//判断是否为空栈
}


int STsize(ST* pst)
{
	assert(pst);
	return pst->top;//返回当前栈上的元素个数。
}

int main()
{
	ST st;
	STInit(&st);
	STPush(&st, 1);
	STPush(&st, 2);
	STPush(&st, 3);
	STPush(&st, 4);
	STPush(&st, 5);
	STPush(&st, 6);
	while (!STEmpty(&st))
	{
		printf("%d", STTop(&st));
		STPop(&st);
	}

	STDestroy(&st);
	return 0;
}

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

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

相关文章

Pytorch基础:torch.load_state_dict()方法在加载时不会检查类型

相关阅读 Pytorch基础https://blog.csdn.net/weixin_45791458/category_12457644.html?spm1001.2014.3001.5482 笔者在使用torch.nn.module的load_state_dict中出现了一个问题&#xff0c;一个被注册的张量在加载后居然没有变化&#xff0c;一开始以为是加载出现了问题&#…

ATTCK的优缺点分别是什么

ATT&CK(Adversarial Tactics, Techniques, and Common Knowledge)框架是一个广泛使用的资源,它提供了对网络威胁的深入洞察,特别是关于攻击者可能采取的战术、技术和程序(TTPs)。以下是ATT&CK框架的优缺点: 优点: 全面的威胁情报:ATT&CK框架详细描述了各种…

Linux基础之gcc/g++

目录 一、gcc/g的介绍 二、一个程序的翻译过程 2.1 预处理阶段 2.2 编译阶段 2.3 汇编阶段 2.4 链接阶段 三、动静态库简介 四、动静态库的优缺点 一、gcc/g的介绍 首先&#xff0c;先简单的介绍一下gcc/g。 GCC&#xff08;GNU Compiler Collection&#xff09;是一个…

MySql安装到配置-超详细版

哈喽宝子们&#xff0c;好久不见&#xff0c;大一五一有没有出去玩呀~反正我是没有出去&#xff0c;就5月1号那天晚上跟室友去看了个电影&#xff0c;然后这几天基本都在宿舍“卷”&#xff0c;其实也不是啦&#xff0c;就是学习学习&#xff0c;因为一方面&#xff0c;暑期实习…

debian10 (armbian) 配置CUPS 服务

更新apt apt-update安装相关软件 apt-get install ghostscript apt-get install dc apt-get install foomatic-db-engine apt-get install cups3.修改配置文件 nano /etc/cups/cupsd.conf Listen localhost:631改为 Listen 0.0.0.0:631 以下四段配置加入Allow All # Only li…

大模型公开可用的模型检查点或 API

文章目录 公开可用的模型检查点或 APILLaMA 变体系列大语言模型的公共 API 公开可用的模型检查点或 API 众所周知&#xff0c;大模型预训练是一项对计算资源要求极高的任务。因此&#xff0c;经过预训练的公开模型检查点&#xff08;Model Checkpoint&#xff09;对于推动大语言…

2024牛客五一集训派对day2 Groundhog Looking Dowdy 个人解题思路

前言&#xff1a; 被实验室教练要求要打的这次五一牛客的训练赛&#xff0c;这些区域赛难度的题对于大一的我来说难度实在是太高了&#xff0c;我和我的队友只写了一些非常简单的签到题&#xff0c;其他题目都没怎么看&#xff08;我们太弱了&#xff09;&#xff0c;但我可以分…

Spring Cloud学习笔记(Hystrix):execute,queue,observe,toObservable样例和特性

这是本人学习的总结&#xff0c;主要学习资料如下 - 马士兵教育 1、Overview2、execute()2.1、Overview2.2、示例 3、queue()3.1、Overview3.2、示例 4、observe()4.1、Overview4.2、示例 5、toObservable()5.1、observe()和toObservable()的区别 1、Overview 我们知道Hystrix…

一文看懂卷积神经网络CNN(1)—前馈神经网络

目录 参考资料 一、神经网络 1、人脑神经网络 2、人工神经网络 3、神经网络的发展历史 二、前馈神经网络 1、神经元 &#xff08;1&#xff09;Sigmoid型函数 ① Logistic函数 ②Tanh函数 ③两个函数形状对比 &#xff08;2&#xff09;ReLU函数 ① 带泄露的ReLU函…

vue 设置输入框只能输入数字且只能输入小数点后两位,并且不能输入减号

<el-input v-model.trim"sb.price" placeholder"现价" class"input_w3" oninput"valuevalue.replace(/[^0-9.]/g,).replace(/\.{2,}/g,.).replace(/^(\-)*(\d)\.(\d\d).*$/,$1$2.$3)"/> 嘎嘎简单、、、、、、、、、

微软如何打造数字零售力航母系列科普08 - Yobe 如何联手微软Azure,安全使用客户数据,预测客户购买行为?

Yobe 如何联手Azure&#xff0c;安全使用客户数据&#xff0c;预测客户购买行为&#xff1f; 在当今数据驱动的世界中&#xff0c;了解客户行为并有能力通过数据和分析预测客户意图是企业保持竞争力所应具备的首要优势。Yobi由Max Snow、Bill Wise和Tom Griffiths于2019年创立&…

【软考高项】三十一、成本管理4个过程

一、规划成本管理 1、定义、作用 定义&#xff1a;确定如何估算、预算、管理、监督和控制项目成本的过程作用&#xff1a;在整个项目期间为如何管理项目成本提供指南和方向 应该在项目规划阶段的早期就对成本管理工作进行规划&#xff0c;建立各成本管理过程的基本框架&…

题目:极速返航

问题描述&#xff1a; 解题思路&#xff1a; 看到题目要求最大值最小&#xff0c;最小值最大&#xff1a;一眼二分答案。二分的时间复杂度是O(log n)。 二分枚举可能的答案X。check()函数判断合法情况。 AC代码&#xff1a; #include<bits/stdc.h> using namespace std…

算法课程笔记——蓝桥云课第六次直播

&#xff08;只有一个数&#xff0c;或者因子只有一个&#xff09;先自己打表&#xff0c;找找规律函数就是2的n次方 异或前缀和 相等就抵消 先前缀和再二分

OpenCV(一) —— OpenCV 基础

1、OpenCV 简介 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个基于 BSD 许可开源发行的跨平台的计算机视觉库。可用于开发实时的图像处理、计算机视觉以及模式识别程序。由英特尔公司发起并参与开发&#xff0c;以 BSD 许可证授权发行&#xff0c…

【深度学习】位置编码

一、引言 Self-Attention并行的计算方式未考虑输入特征间的位置关系&#xff0c;这对NLP来说是不可接受的&#xff0c;毕竟一个句子中每个单词都有着明显的顺序关系。Transformer没有RNN、LSTM那样的顺序结构&#xff0c;所以Transformer在提出Self-Attention的同时提出了Posi…

ruoyi漏洞总结

若依识别 黑若依 :icon hash"-1231872293 绿若依 :icon hash"706913071” body" 请通过前端地址访 " body" 认证失败&#xff0c;无法访问系统资源 " 如果页面访问显示不正常&#xff0c;可添加默认访问路径尝试是否显示正常 /login?redi…

STM32 F103C8T6学习笔记17:类IIC通信(SMBus协议)—MLX90614红外非接触温度计

今日学习配置MLX90614红外非接触温度计 与 STM32 F103C8T6 单片机的通信 文章提供测试代码讲解、完整工程下载、测试效果图 本文需要用到的大概基础知识&#xff1a;1.3寸OLED配置通信显示、IIC通信、 定时器配置使用 这里就只贴出我的 OLED驱动方面的网址链接了&#xff1a…

QT+串口调试助手+基本版

一、创建串口调试助手UI界面 1、首先生成串口连接必要参数界面&#xff0c;删除关闭串口控件 2、给参数下拉框添加常见的选项&#xff0c;删除关闭串口控件 3、将串口调试助手参数界面布局整齐&#xff0c;删除关闭串口控件 4、更改控件名字&#xff0c;方便后续编程&#xff…

深度学习中权重初始化的重要性

深度学习模型中的权重初始化经常被人忽略&#xff0c;而事实上这是非常重要的一个步骤&#xff0c;模型的初始化权重的好坏关系到模型的训练成功与否&#xff0c;以及训练速度是否快速&#xff0c;效果是否更好等等&#xff0c;这次我们专门来看看深度学习中的权重初始化问题。…