数据结构------栈的介绍和实现

目录

1.栈的一些初步认识

2.栈的实现

3.相关的函数介绍

(1)栈的初始化

(2)栈的销毁

(3)栈的数据插入 

(6)判断是否为空

(7)栈的大小

4.栈的实现完整代码

(1)stack.h

(2)stack.c

(3)test.c

5.栈的应用--有效的括号


1.栈的一些初步认识

相信前面看过我的函数栈帧的创建和销毁这篇博客的小伙伴们对于栈已经有了一个初步的了解

因为在那个博客里面,我们提到了栈顶指针,栈底指针,压栈,出栈等等一些专业术语;

现在我们来系统的认识一下栈:

栈实际上也是一个存储数据的结构,和我们的线性表是一样的,但是栈肯定是有自己的独特之处的,否则也不会作为一个单独的数据结构存在,确实,栈的特殊性就在于我们的数据都是从栈顶进入,栈顶出去,这个就是栈的特殊之处;

栈的这个特性使得先进去的数据后出来,后进栈的数据先出来,这个有什么好处呢?我们现在可能还体会不到,我通过一个例子大家就可以体会到栈的用途,栈是有用的;

比如我们想要判断一串符号的顺序:看看是不是一一对应的,例如{(【】)}这个肯定就是一一对应的符号组合,但是对于{【(}】)这个就不是一一对应的符号,我们是用肉眼可以看出来的,但是如果有题目让我们设计程序进行判断呢?

拿这个{(【】)}作为案例,我们的{先进栈,(再进栈,【再进栈,这个时候我们的左边的括号都判断完了,我们需要判断右边的符号和左边的是不是一一对应的,这个时候就可以使用栈这个数据结构,因为我们的栈是后进先出,前面的3个符号进栈之后,我们就可以让他们依次出栈和我们后面的几个符号进行比较,例如这里的大括号第一个进栈,小括号第二个进栈,中括号第三个进栈,我们要向看看是否匹配,就只需要判断第四个的符号中括号和我们第一个出栈的符号是否匹配,这个时候栈这个数据结构就可以帮助我们判断这个一串符号前后是不是一一对应的。

2.栈的实现

我们还是写一个系统的文件,包括栈的实现的头文件,源文件和测试文件这三个文件;

我们在头文件里面进行相关函数的声明,源文件里面进行相关的函数的定义,测试文件里面定义一个栈进行我们写的函数的测试;

我们这里是定义了一些函数:栈的初始化,栈的销毁,栈里面插入数据,栈里面删除数据,返回栈顶的数据,判断栈是否是空的,栈的大小;

3.相关的函数介绍

(1)栈的初始化

这里就是把数组置空,栈顶的位置设为0,容量设置为0,这里是top指的是栈顶的位置,我们这里初始化为0,实际上指的是栈顶的下一个元素,实际情况下,栈这个时候是空的,我们应该初始化为-1,我们初始化为0方便后面的插入数据,我们插入数据就是在栈顶的下一个位置进行插入的,因此我们初始化为0可以方便后续的数据的插入;

(2)栈的销毁

就是释放掉数组的空间,栈顶位置和栈的容量都设置为0就可以了;

(3)栈的数据插入 

我们要为这个栈开辟空间,把我们要插入的数据给插入进去,再让栈顶的位置加加就行了;

(4)栈的元素删除 

这个就是不断的删除栈顶的元素,让栈顶位置元素不断的弹出,最后不断的让top--,但是这个栈的元素的个数是有限的,肯定不能一直进行top--把,我们调用这个判断是否为空的函数进行断言,因为这个函数判断的是为空的,所以我们断言的时候取非,这个时候过了再进行top--;

(5)取出栈的元素

返回值就是我们取出来的元素,还是要进行断言,因为栈里面的元素个数是有限的,我们肯定不能一直取出元素;

(6)判断是否为空

我们设置布尔值,pst->top为0时候,说明栈里面没有元素,是空的,我们就返回true,否则就返回false;

(7)栈的大小

我们还是返回pst->top表示的是栈顶的下一个位置,下表和个数是相差1的,如果是2个元素,我们的pst->top表示的是栈顶的下一个元素位置,下标是从0开始的,栈顶的下一个元素就是第三个元素,下标就是2,我们返回的就是2个元素的个数; 

4.栈的实现完整代码

(1)stack.h

#pragma once
#include<stdbool.h>
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int sldatatype;
typedef struct stack
{sldatatype* a;int top;int capacity;
}stack;void stackinit(stack* pst);void stackdestory(stack* pst);void stackpush(stack* pst, sldatatype x);void stackpop(stack* pst);sldatatype stacktop(stack* pst);bool stackempty(stack* pst);int size(stack* pst);

(2)stack.c

#include"stack.h"void stackinit(stack* pst)
{assert(pst);pst->a = NULL;pst->top = 0;//指向栈顶的下一个元素pst->capacity = 0;
}void stackdestory(stack* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = 0;pst->capacity = 0;
}void stackpush(stack* pst, sldatatype x)
{if (pst->top == pst->capacity){int newcapacity = pst->capacity == 0 ? 4 : (pst->capacity * 2);sldatatype* temp = (sldatatype*)realloc(pst->a, newcapacity * sizeof(sldatatype));if (temp == NULL){perror("realloc fail!");return;}pst->a = temp;pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}void stackpop(stack* pst)
{assert(pst);assert(!stackempty(pst));pst->top--;
}sldatatype stacktop(stack* pst)
{assert(pst);assert(!stackempty(pst));return pst->a[pst->top - 1];
}bool stackempty(stack* pst)
{assert(pst);return pst->top == 0;
}int size(stack* pst)
{assert(pst);return pst->top;
}

(3)test.c

#include"stack.h"void test1()
{stack s1;stackinit(&s1);stackpush(&s1, 1);stackpush(&s1, 2);stackpush(&s1, 3);stackpush(&s1, 4);while (!stackempty(&s1)){printf("%d ", stacktop(&s1));stackpop(&s1);}stackdestory(&s1);
}
int main()
{test1();return 0;
}

我们这里进行栈里面的数据打印的时候是设置了一个循环,我们每打印一个数据,就弹出栈顶位置的元素,这个时候就有一个新的数据成为栈顶,我们再打印新的栈顶位置数据 。

5.栈的应用--有效的括号

这里的应用就是我们开始提到的括号的匹配问题,我们要判断这个括号之间是否是相互匹配的;

因为现阶段我们还是使用C语言进行实现,所以我们要自己实现栈,如果是C++,我们可以使用相应的一些库,我们可以直接进行调用,这里我们就把上面实现的函数复制过来就可以了。

代码展示:

#include<stdbool.h>
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef char sldatatype;
typedef struct stack
{sldatatype* a;int top;int capacity;
}stack;void stackinit(stack* pst);void stackdestory(stack* pst);void stackpush(stack* pst, sldatatype x);void stackpop(stack* pst);sldatatype stacktop(stack* pst);bool stackempty(stack* pst);int size(stack* pst);void stackinit(stack* pst)
{assert(pst);pst->a = NULL;pst->top = 0;//指向栈顶的下一个元素pst->capacity = 0;
}void stackdestory(stack* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = 0;pst->capacity = 0;
}void stackpush(stack* pst, sldatatype x)
{if (pst->top == pst->capacity){int newcapacity = pst->capacity == 0 ? 4 : (pst->capacity * 2);sldatatype* temp = (sldatatype*)realloc(pst->a, newcapacity * sizeof(sldatatype));if (temp == NULL){perror("realloc fail!");return;}pst->a = temp;pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}void stackpop(stack* pst)
{assert(pst);assert(!stackempty(pst));pst->top--;
}sldatatype stacktop(stack* pst)
{assert(pst);assert(!stackempty(pst));return pst->a[pst->top - 1];
}bool stackempty(stack* pst)
{assert(pst);return pst->top == 0;
}int size(stack* pst)
{assert(pst);return pst->top;
}
bool isValid(char* s) 
{stack s1;stackinit(&s1);while(*s){if(*s=='('||*s=='['||*s=='{'){stackpush(&s1,*s);}else{if(stackempty(&s1)){stackdestory(&s1);return false;}char top=stacktop(&s1);stackpop(&s1);if(*s==']'&&top!='['||*s=='}'&&top!='{'||*s==')'&&top!='('){stackdestory(&s1);return false;}else{}}++s;}bool ret=stackempty(&s1);stackdestory(&s1);return ret;
}

(1)这个代码看上去比较复杂,实际上前面的很多都是在自己实现一个栈,只有inValid才是真正的一个接口函数,其他的都是为这个函数服务的,我们的inValid函数调用其他的函数进行相应的判断;

(2)因为我们这里是对符号进行判断,所以我们的头文件里面的int需要修改为char类型数据,这个时候我们的typedef int sldatatype的作用就显示了出来。

 

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

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

相关文章

【数据结构(邓俊辉)学习笔记】列表01——从向量到列表

文章目录 0.概述1. 从向量到列表1.1 从静态到动态1.2 从向量到列表1.3 从秩到位置1.4 列表 2. 接口2.1 列表节点2.1.1 ADT接口2.1.2 ListNode模板类 2.2 列表2.2.1 ADT接口2.2.2 List模板类 0.概述 学习了向量&#xff0c;再介绍下列表。先介绍下列表里的概念和语义&#xff0…

【HM】DevEco Studio如何使用代码编程AI助手

大家可能都有用过或了解过github copilot插件&#xff0c;确实为我们编码智能、提升开发效率有很大的帮助。推荐两款国产的ai编程插件&#xff0c;分别是华为的CodeArts Snap和阿里的通义灵码。 DevEco 中如何安装通义灵码&#xff1f; 一、下载通义灵码离线安装包 打开官网…

每日OJ题_贪心算法二⑤_力扣870. 优势洗牌(田忌赛马)

目录 力扣870. 优势洗牌&#xff08;田忌赛马&#xff09; 解析代码 力扣870. 优势洗牌&#xff08;田忌赛马&#xff09; 870. 优势洗牌 难度 中等 给定两个长度相等的数组 nums1 和 nums2&#xff0c;nums1 相对于 nums2 的优势可以用满足 nums1[i] > nums2[i] 的索引…

golang学习笔记(内存逃逸分析)

golang的内存逃逸 逃逸分析&#xff08; Escape analysis&#xff09; 是指由编译器决定内存分配的位置&#xff0c; 不需要程序员指定。 函数中申请一个新的对象。 如果分配在栈中&#xff0c; 则函数执行结束可自动将内存回收&#xff1b;如果分配在堆中&#xff0c; 则函数…

解决layui的bug 在layui tree 组件中 禁用选中父节点后自动选中子节点功能

最近做权限管理后台&#xff0c;用了layui tree 组件&#xff0c;发现选中了父节点后&#xff0c;自动选中了子节点。不满足现实业务需求。所以微调了下源代码。 在用树形组件中&#xff0c;在用文档中 tree.setChecked(demoId, [2, 3]); //批量勾选 id 为 2、3 的节点 用这句…

linux 服务器利用阿里网盘API实现文件的上传和下载

文章目录 背景脚本初始化 阿里云盘API工具 aligo安装aligoaligo教程实战parse.py 演示上传文件上传文件夹下载文件下载文件夹 背景 最近在用ubuntu系统做实验&#xff0c;而ubuntu 系统的文件上传和下载操作很麻烦&#xff1b; 于是便打算使用阿里网盘的API 进行文件下载与上传…

腾锐D2000-8 MXM VPX,全国产,可广泛应用于边缘计算网关、入侵检测、VPN、网络监控等等应用领域

腾锐D2000-8 MXM VPX 1. 概述 XMVPX-108 是一款基于飞腾 D2000/8 处理器的低功耗逻辑运算和图形处理 VPX 刀片&#xff0c; 板贴 32GB DDR4 内存&#xff0c;搭载飞腾 X100 套片&#xff0c;满足通用 IO 接口功能。GPU 采用 MXM 小型插卡形式&#xff0c; 搭配 8GB 显卡。提供…

NIO和NIO.2对比

Java NIO (New Input/Output) 是从Java 1.4版本开始引入的一个新的I/O API&#xff0c;用于替代原来的BIO&#xff08;Blocking I/O&#xff09;API。NIO提供了更加灵活和高效的网络通信方式&#xff0c;特别适合于高吞吐量的网络编程。NIO的主要特点是非阻塞模式&#xff0c;它…

3.4 无关、基和维度

这一节是关于子空间的真实大小。对于 m n m\times n mn 的矩阵&#xff0c;它有 n n n 个列&#xff0c;但是它真正的维数不一定为 n n n&#xff0c;维数可以由无关列的个数来得到。列空间的实际维度就是秩 r r r。 无关的概念是用于向量空间中的任意向量 v 1 , . . . ,…

【LAMMPS学习】八、基础知识(5.7)Drude感应偶极子

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

人工智能|推荐系统——工业界的推荐系统之召回

基于物品的协同过滤 ⽤索引,离线计算量⼤,线上计算量⼩ Swing额外考虑重合的⽤户是否来⾃⼀个⼩圈⼦,两个⽤户重合度⼤,则可能来⾃⼀个⼩圈⼦,权重降低。 基于用户的协同过滤 同样是离线计算索引,在线召回的流程 离散特征处理 Embedding 层参数数量=向量维度 类别数量 矩

DS高阶:图论算法经典应用

一、最小生成树&#xff08;无向图&#xff09; 在了解最小生成树算法之前&#xff0c;我们首先要先了解以下的准则&#xff1a; 连通图中的每一棵生成树&#xff0c;都是原图的一个极大无环子图&#xff0c;即&#xff1a;从其中删去任何一条边&#xff0c;生成树就不在连通&a…

mysql查询数据不对

sum(id)是算id这一列的数值总和&#xff0c;无论主键与否&#xff0c;sum都是算数值总和 count(id)或count(*)是算当前列的行数&#xff0c;id是主键才行

FIFO Generate IP核使用——AXI接口FIFO简介

AXI接口FIFO是从Native接口FIFO派生而来的。AXI内存映射接口提供了三种样式&#xff1a;AXI4、AXI3和AXI4-Lite。除了Native接口FIFO支持的应用外&#xff0c;AXI FIFO还可以用于AXI系统总线和点对点高速应用。 AXI接口FIFO不支持Builtin FIFO和 Shift Register FIFO配置。 当…

WebSocket 多屏同显和异显

介绍 多屏同显:通过在一个应用上进行操作之后,另一个应用也能跟着一起发生改变,例如app1播放了晴天这首音乐,那么app2也要同步播放这首音乐,确保所有屏幕显示的内容完全相同。多屏异显:每个屏幕可以显示不同的内容,或者在内容更新时存在一定的延迟,而不需要严格保持同步…

专业渗透测试 Phpsploit-Framework(PSF)框架软件小白入门教程(四)

本系列课程&#xff0c;将重点讲解Phpsploit-Framework框架软件的基础使用&#xff01; 本文章仅提供学习&#xff0c;切勿将其用于不法手段&#xff01; 继续接上一篇文章内容&#xff0c;讲述如何进行Phpsploit-Framework软件的基础使用和二次开发。 当我们牢记登陆账户、…

题目:线性代数

问题描述&#xff1a; 解题思路&#xff1a; 列相乘&#xff0c;然后行相加。 注意点&#xff1a;由于元素数据范围最大为1e6&#xff0c;两个元素相乘乘积最大为1e12&#xff0c;如果元素类型为int则在乘的过程中就会爆炸&#xff0c;所以需要开long long类型。 AC代码…

Redis---------分布式锁Redisson

概述 Redisson入门 第一步&#xff1a;引入依赖 <dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.13.6</version></dependency> 第二步&#xff1a;配置文件 import org.redisson…

MapReduce概述

批处理模式 首先我们需要先了解一个概念&#xff1a;批处理模式 批处理模式是一种最早进行大规模数据处理的模式。 批处理非常适合需要访问整个数据集合才能完成的计算工作。 批处理主要操作大规模静态数据集,并在整体数据处理完毕后返回结果。 例如,在计算总数和平均数时,必须…

基于小程序实现的投票评选系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;spring…