栈——“数据结构与算法”

news2024/11/19 0:19:24

各位uu们,好久不见!!!甚是想念!!!

好久没有更新我们的数据结构与算法专栏啦,最近小雅兰新学了很多知识,第一时间就想迫不及待地和C站的小伙伴们分享呢,下面,让我们进入栈的世界吧


栈 


栈的概念及结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。

进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。

栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据也在栈顶。

 

几个习题

1.一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出栈的顺序是( B )。

A 12345ABCDE

B EDCBA54321

C ABCDE12345

D 54321EDCBA

2.若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是( C )

A 1,4,3,2

B 2,3,4,1

C 3,1,4,2

D 3,4,2,1

A选项:先进1,再立马出1,再进2 3 4,然后再出4 3 2

B选项:先进1 2,然后出2,然后进3,出3,进4,出4,最后再出1

C选项:无论怎么进出,都不会出现这样的组合,因为:都没有两个连续的数

D选项:先进1 2 3,再出3,然后进4,出4,再出2,最后出1

栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。

 

 下面,我们开始用代码来实现它:

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;//栈顶
	int capacity;//容量
}Stack;

这已经是一个常规操作了,利用结构体和typedef,定义一个栈

初始化栈:

// 初始化栈 
void StackInit(Stack* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->top = 0;
	pst->capacity = 0;
}

销毁栈:

// 销毁栈 
void StackDestroy(Stack* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}

入栈:

这边使用了三目操作符 

https://xiaoyalan.blog.csdn.net/article/details/128941939

https://xiaoyalan.blog.csdn.net/article/details/128993533

这是小雅兰写的操作符的相关知识点,有兴趣的可以来看看

// 入栈 
void StackPush(Stack* pst, STDataType x)
{
	assert(pst);
	//扩容
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		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;
	pst->top++;
}

检测栈是否为空:

// 检测栈是否为空
bool StackEmpty(Stack* pst)
{
	assert(pst);
	if (pst->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}
}

当然,这是一种比较low的写法,下面来看看这种写法:

// 检测栈是否为空
bool StackEmpty(Stack* pst)
{
	return pst->top==0;
}

这种写法,如此简洁,也实现了它该具备的功能,这样岂不是更好吗

出栈:

// 出栈 
void StackPop(Stack* pst)
{
	assert(pst);
	assert(!StackEmpty(pst));
	pst->top--;
}

获取栈顶元素:

// 获取栈顶元素 
STDataType StackTop(Stack* pst)
{
	assert(pst);
	assert(!StackEmpty(pst));
	return pst->a[pst->top - 1];
}

获取栈中有效元素的个数:

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

栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

 要搞清楚这个概念,首先要明白”栈“原来的意思,如此才能把握本质。栈,存储货物或供旅客住宿的地方,可引申为仓库、中转站,所以引入到计算机领域里,就是指数据暂时存储的地方,所以才有进栈、出栈的说法。


首先,系统或者数据结构栈中数据内容的读取与插入(压入)push和 弹出pop是两回事。

压入是增加数据,弹出是删除数据 ,这些操作只能从栈顶即最低地址作为约束的接口界面入手操作 ,但读取栈中的数据是随便的,没有接口约束之说。很多人都误解这个理念从而对栈产生困惑。而系统栈在计算机体系结构中又起到一个跨部件交互的媒介区域的作用,即 cpu 与内存的交流通道 ,cpu只从系统给我们自己编写的应用程序所规定的栈入口线性地读取执行指令, 用一个形象的词来形容它就是pipeline(管道线、流水线)。cpu内部交互具体参见 EU与BIU的概念介绍。


栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针。


栈是允许在同一端进行插入和删除操作的特殊线性表。允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom)栈底固定,而栈顶浮动栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)。栈也称为先进后出表。
栈可以用来在函数调用的时候存储断点,做递归时要用到栈。

以上定义是在经典计算机科学中的解释。


在计算机系统中,栈则是一个具有以上属性的动态内存区域。程序可以将数据压入栈中,也可以将数据从栈顶弹出。在i386机器中,栈顶由称为esp的寄存器进行定位。压栈的操作使得栈顶的地址减小,弹出的操作使得栈顶的地址增大。


栈在程序的运行中有着举足轻重的作用。最重要的是栈保存了一个函数调用时所需要的维护信息,这常常称之为堆栈帧或者活动记录。堆栈帧一般包含如下几方面的信息:
1.函数的返回地址和参数
2. 临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量。


测试一下此代码的功能:

void testStack1()
{
	Stack st;
	StackInit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);
	printf("栈顶元素:%d\n", StackTop(&st));
	printf("栈中元素个数:%d\n", StackSize(&st));
	StackPop(&st);
	printf("栈顶元素:%d\n", StackTop(&st));
	StackPush(&st, 5);
	StackPush(&st, 6);
	while (!StackEmpty(&st))
	{
		printf("栈顶元素:%d\n", StackTop(&st));
		StackPop(&st);
	}
	StackDestroy(&st);
}
int main()
{
	testStack1();
	return 0;
}


源代码如下:

Stack.h的内容:

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;//栈顶
	int capacity;//容量
}Stack;

// 初始化栈 
void StackInit(Stack* pst);

// 销毁栈 
void StackDestroy(Stack* pst);

// 入栈 
void StackPush(Stack* pst, STDataType x);

// 出栈 
void StackPop(Stack* pst);

// 获取栈顶元素 
STDataType StackTop(Stack* pst);

// 获取栈中有效元素个数 
int StackSize(Stack* pst);

// 检测栈是否为空 
bool StackEmpty(Stack* pst);

Stack.c的内容:

#include"Stack.h"
// 初始化栈 
void StackInit(Stack* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->top = 0;
	pst->capacity = 0;
}
// 销毁栈 
void StackDestroy(Stack* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}
// 入栈 
void StackPush(Stack* pst, STDataType x)
{
	assert(pst);
	//扩容
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		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;
	pst->top++;
}
// 检测栈是否为空
bool StackEmpty(Stack* pst)
{
	assert(pst);
	if (pst->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}
	//return pst->top==0;
}
// 出栈 
void StackPop(Stack* pst)
{
	assert(pst);
	assert(!StackEmpty(pst));
	pst->top--;
}
// 获取栈顶元素 
STDataType StackTop(Stack* pst)
{
	assert(pst);
	assert(!StackEmpty(pst));
	return pst->a[pst->top - 1];
}

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

好啦,小雅兰今天分享的栈的知识点就到这里啦,继续加油学数据结构与算法噢!!!

 

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

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

相关文章

LeetCode高频算法刷题记录3

文章目录 1. 搜索旋转排序数组【中等】1.1 题目描述1.2 解题思路1.3 代码实现 2. 有效的括号【简单】2.1 题目描述2.2 解题思路2.3 代码实现 3. 买卖股票的最佳时机【简单】3.1 题目描述3.2 解题思路3.3 代码实现 4. 环形链表【简单】4.1 题目描述4.2 解题思路4.3 代码实现 5. …

ChatGPT Plus 插件最全解读

前言&#xff1a; OpenAI放出大招&#xff0c;向所有ChatGPT Plus用户开放联网功能和众多插件&#xff0c;允许ChatGPT访问互联网并使用70个第三方插件。 本批第三方插件能够全方位覆盖衣食住行、社交、工作以及学习等日常所需&#xff0c;基本上能够扮演24小时私人助理的角色…

SaleSmartly聊天机器人如何帮助您的电商业务

从基于规则的机器人到虚拟助手&#xff0c;聊天机器人正在成为网络交互的标准。越来越多的企业正在使用它们来吸引客户、改善客户服务并增强用户体验。现在有非常多的软件也提供聊天机器人的帮助&#xff0c;比如SaleSmartly&#xff08;ss客服&#xff09;&#xff0c;本文以它…

【包真】我的第一次webpack优化,首屏渲染从9s到1s

目录 前言 1.生产环境关闭productionSourceMap、css sourceMap 2.分析大文件&#xff0c;找出内鬼 3. 逐个包优化 TreeShaking 使用cdn加载第三方js 懒加载有间接依赖的包 moment.js的优化 还有进步空间&#xff1f; 最后 前言 本文基于vue2(虽然vue…

我的小实验项目:实现人体红外采集控制LED灯亮灭

从传感器电路图中找到红外感应&#xff0c;找到接口D2&#xff0c;可以看出&#xff0c;采集的信息从D2进入 从核心板电路图找到D2接口&#xff0c;发现引脚为PB8 并用相似的方法&#xff0c;找到用于代表有人无人的LED灯 在STM32CubeMx里设置 在Keil里设置代码 main.c&#x…

智慧物业如何整合生态资源,小程序技术或成为突破口

数字物业和智慧社区成为了当前数字化转型的热点领域。这些新兴技术的应用&#xff0c;不仅为业主提供了更加便捷、高效的服务&#xff0c;也为物业公司和城市管理带来了全新的运营模式和管理方式。 根据数据显示&#xff0c;截至2021年底&#xff0c;中国物业服务企业智慧化改造…

基于Java+SpringBoot+Vue前后端分离网上银行系统设计与实现(视频讲解)

博主介绍&#xff1a;✌全网粉丝3W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

Element-ui中el-table展开行

类似这样的需求还记录不记录呢&#xff0c;其实我觉得是没必要的&#xff0c;但是想来还是记录一下吧&#xff0c;因为element-ui里面组件本身也很多&#xff0c;其中el-table的配置样式需求更是很多很多&#xff0c;所以这还是决定来记录一下&#xff0c;以后再有类似的需求也…

linux内核篇-输入输出系统(块设备,字符设备)

计算机系统的输入和输出系统都有哪些呢&#xff1f;有键盘、鼠标、显示器、网卡、硬盘、打印机、CD/DVD 等等&#xff0c;多种多样。但是对于操作系统来讲&#xff0c;却是一件复杂的事情&#xff0c;因为这么多设备&#xff0c;形状、用法、功能都不一样&#xff0c;怎么才能统…

SpringBoot中整合Swagger2接口文档

目录 1、maven依赖 2、swagger2 注解整体说明 2.1、请求类的描述 2.2、方法和方法参数的描述 2.3、方法的响应状态的描述 2.4、对象的描述 3、请求类的描述 3.1、Api&#xff1a;请求类的说明 3.2、示例&#xff1a; 4、方法和方法参数的描述 4.1、ApiOperation&#xff1a…

Linux 中的文件类型

目录 Linux文件类型说明 软链接 软链接特点 软链接工作过程 正常原文件a工作流程 文件a的软链接工作流程 硬链接 硬链接的特点 文件a的硬链接工作流程 软链接与硬链接的比较 测试软链接以及硬链接 1.进入根目录 2.创建test目录 3.进入test目录中&#xff0c;并创建a…

基于Redis的分布式锁,Redisson的简单使用和常用配置

介绍 Redisson是一个在Redis基础上实现的Java驻内存数据网格。Redisson提供了使用Redis的最简单最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离&#xff0c;从而让使用者能够将精力更集中的放在处理业务逻辑上。 Redisson官方文档地址&#xff1a;https://githu…

蛋糕烘焙店小程序开发 让生活多点甜

蛋糕甜品因为较高的颜值、香甜的口感深受大众喜欢&#xff0c;当我们路过一家蛋糕烘焙店的时候&#xff0c;飘香的味道让我们流连忘返。但是互联网时代&#xff0c;各个行业都在转型&#xff0c;蛋糕烘焙店也需要由传统线下店面向线上线下结合的方式转变&#xff0c;以求摆脱区…

数据对象属性分类

数据集由数据对象组成&#xff0c;一个数据对象代表一个实体。数据对象又称样本、实例、数据点或对象。属性&#xff08;attribute&#xff09;是一个数据字段&#xff0c;表示数据对象的一个特征。属性向量&#xff08;或特征向量&#xff09;是用来描述一个给定对象的一组属性…

MySQL之单表访问方法

前言 本文章收录在MySQL性能优化原理实战专栏&#xff0c;点击此处查看更多优质内容。 本文摘录自 ▪ 小孩子4919《MySQL是怎样运行的&#xff1a;从根儿上理解MySQL》 对于我们这些MySQL的使用者来说&#xff0c;MySQL其实就是一个软件&#xff0c;平时用的最多的就是查询功…

快码住!!! 二叉树概念、重要性质、存储结构 技巧大总结!

文章目录 树树的概念树的表示树在实际中的应用 二叉树二叉树的概念特殊的二叉树 二叉树的性质二叉树性质应用的练习题 二叉树的存储结构顺序结构链式结构 树 树的概念 树是一种非线性的数据结构&#xff0c;它是由n(n>0)个有限结点组成的一个具有层次关系的集合。把它叫做…

语言模型及Word2vec与Bert简析

语言模型可以对一段文本的合理性概率进行估计&#xff0c;对信息检索&#xff0c;机器翻译&#xff0c;语音识别等任务有着重要的作用。就以前的学习笔记&#xff0c;本文简单总结了NLP语言模型word2vec和bert分享给大家&#xff0c;疏漏之处&#xff0c;望请指出&#xff0c; …

Go语言的简介和环境搭建

Go语言的简介和环境搭建 带你了解什么是Go语言 如何安装和配置Go的开发环境 静态强类型&#xff0c;编译型语言&#xff01;&#xff01;&#xff01; 1.简介 1.1介绍 Go 也称为 Golang&#xff0c;两个是一个东西。谷歌弄得。创造者都是大佬&#xff0c;所以说这个编程语言很…

PSP - AlphaFold2 Multimer 的 Heteromer (异聚体) MSA 逻辑

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/130733737 同源多聚体 (Homomer) 是由相同的蛋白质亚基组成的,而异源多聚体 (Heteromer) 是由不同的蛋白质亚基组成的。同源多聚体的亚基之间通常有对称的相…

BFT 最前线 | OpenAI开放网络浏览和插件;“360AI商店”上线;Bing市场份额不升反降;亚马逊机器人配送中心投产

原创 | BFT机器人 AI视界 TECHNOLOGY NEWS 01 OpenAI将向所有ChatGPT Plus用户推出网络浏览和插件 OpenAI将向所有ChatGPT Plus用户推出网络浏览和插件近日&#xff0c;OpenAI发文称&#xff0c;将在本周&#xff08;5.15-5.21日&#xff09;内向所有ChatGPT Plus用户推出网络…