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

目录

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.rhkb.cn/news/318852.html

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

相关文章

iBarcoder for Mac:一站式条形码生成软件

在数字化时代&#xff0c;条形码的应用越来越广泛。iBarcoder for Mac作为一款专业的条形码生成软件&#xff0c;为用户提供了一站式的解决方案。无论是零售、出版还是物流等行业&#xff0c;iBarcoder都能轻松应对&#xff0c;助力用户实现高效管理。 iBarcoder for Mac v3.14…

win11 Terminal 部分窗口美化

需求及分析&#xff1a;因为在 cmd、anaconda prompt 窗口中输入命令较多&#xff0c;而命令输入行和输出结果都是同一个颜色&#xff0c;不易阅读&#xff0c;故将需求定性为「美化窗口」。 美化结束后&#xff0c;我在想是否能不安装任何软件&#xff0c;简单地通过调整主题颜…

windows驱动开发-PNP管理器

PNP技术是由Microsoft提出的&#xff0c;英文Plug and play的缩写&#xff0c;中译即插即用&#xff0c;意思是系统自动侦测周边设备和板卡并自动安装设备驱动程序&#xff0c;做到插上就能用&#xff0c;无须人工干预&#xff0c;是Windows自带的一项技术。所谓即插即用是指将…

从零开始搭建一个vue项目

从零开始搭建一个vue项目 一、环境准备 1.1 安装node.js 选择合适的LTS版本&#xff0c;然后下载安装&#xff0c;安装地址&#xff1a;https://nodejs.org/en/download 在命令行中查看已安装的node.js版本 node -v v14.14.01.2 切换为淘宝的镜像源 解决国内下载慢的问题,…

极简shell制作

&#x1f30e;自定义简单shell制作 &#xff08;ps: 文末有完整代码&#xff09; 文章目录&#xff1a; 自定义简单shell制作 简单配置Linux文件 自定义Shell编写 命令行解释器       获取输入的命令       字符串分割       子进程进行进程替换 内建命令…

.NET 检测地址/主机/域名是否正常

&#x1f331;PING 地址/主机名/域名 /// <summary>/// PING/// </summary>/// <param name"ip">ip</param>/// <returns></returns>public static bool PingIp(string ip){System.Net.NetworkInformation.Ping p new System.N…

OpenAI 新推出 AI 问答搜索引擎——SearchGPT 震撼登场

您的浏览器不支持 video 标签。 OpenAI-SearchGPT 近日&#xff0c;OpenAI 曝光了自己的一款令人瞩目的 AI 问答搜索引擎——SearchGPT。这款搜索引擎带来了全新的搜索体验&#xff0c;给整个行业带来了巨大的压力。 SearchGPT 支持多种强大的功能。首先&#xff0c;它能够通过…

蓝桥杯练习系统(算法训练)ALGO-949 勇士和地雷阵

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 勇士们不小心进入了敌人的地雷阵&#xff08;用n行n列的矩阵表示&#xff0c;*表示某个位置埋有地雷&#xff0c;-表示某个…

ARP防火墙能够为网络安全贡献什么样的力量

ARP防火墙&#xff08;Address Resolution Protocol Firewall&#xff09;作为网络安全的一环&#xff0c;起到保护网络免受ARP欺骗攻击的关键作用。今天德迅云安全给您介绍ARP防火墙的相关方面&#xff0c;帮助您深入了解和认识这一关键的安全措施。 网络安全对于现代社会的信…

金三银四面试题(二十四):享元模式知多少?

什么是享元模式 享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构型设计模式&#xff0c;旨在通过共享对象来减少内存使用&#xff0c;从而提高性能。它主要用于处理大量细粒度对象的情况&#xff0c;通过将这些对象的可共享部分&#xff08;内部状态&#xff09…

毫米波雷达原理(含代码)(含ARS548 4D毫米波雷达数据demo和可视化视频)

毫米波雷达原理 1. 传统毫米波雷达1.1 雷达工作原理1.2 单目标距离估计1.3 单目标速度估计1.4 单目标角度估计1.5 多目标距离估计1.6 多目标速度估计1.7多目标角度估计1.7 总结 3. FMCW雷达数据处理算法4. 毫米波雷达的目标解析(含python代码)5. ARS548 4D毫米波雷达数据demo(含…

MYSQL从入门到精通(二)

1、MYSQL高级概述 【1】架构概述 【2】索引优化 【3】查询截取 【4】mysql锁机制 【5】主从复制 2、MYSQL概述 【1】mysql内核 【2】sql优化工程师 【3】mysql服务器的优化 【4】各种参数常量设定 【5】查询语句优化 【6】主从复制 【7】软硬件升级 【8】容灾百分 【9】sql编…

Flutter笔记:Widgets Easier组件库(1)使用各式边框

Flutter笔记 Widgets Easier组件库&#xff08;1&#xff09;&#xff1a;使用边框 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress o…

Leetcode—377. 组合总和 Ⅳ【中等】

2024每日刷题&#xff08;124&#xff09; Leetcode—377. 组合总和 Ⅳ 算法思想 实现代码 class Solution { public:int combinationSum4(vector<int>& nums, int target) {vector<unsigned long long>dp(target 1);dp[0] 1;for(int i 1; i < target;…

React、React Router 和 Redux 常用Hooks 总结,提升您的开发效率!

Hooks 是 React 16.8 中引入的一种新特性&#xff0c;它使得函数组件可以使用 state 和其他 React 特性&#xff0c;从而大大提高了函数组件的灵活性和功能性。下面分别总结React、React Router 、Redux中常用的Hooks。 常用Hooks速记 React Hooks useState&#xff1a;用于…

社交媒体数据恢复:WorldTalk

WorldTalk数据恢复方法 在本文中&#xff0c;我们将探讨如何恢复在WorldTalk中删除的信息。请注意&#xff0c;这些步骤并不是专门针对WorldTalk软件设计的&#xff0c;而是基于一般的手机数据恢复流程。由于WorldTalk是一款全球5亿人使用的交友APP&#xff0c;用户分别来自中…

EDA(一)Verilog

EDA&#xff08;一&#xff09;Verilog Verilog是一种用于电子系统设计自动化&#xff08;EDA&#xff09;的硬件描述语言&#xff08;HDL&#xff09;&#xff0c;主要用于设计和模拟电子系统&#xff0c;特别是在集成电路&#xff08;IC&#xff09;和印刷电路板&#xff08;…

TCP 协议

TCP协议段格式 源/目的端口号&#xff1a;表示数据是从哪个进程来&#xff0c;到哪个进程去。 序号&#xff1a;发送数据的序号。 确认序号&#xff1a;应答报文的序号&#xff0c;用来回复发送方的。 4 位首部长度&#xff1a;一个 TCP 报头&#xff0c;长度是可变的&#xff…

zotero better notes报错:Error: ReferenceError: topItem is not defined

我的自定义笔记模板名称是&#xff1a;简约风格 然后就遇到了以下报错&#xff1a; Error: ReferenceError: topItem is not defined 解决办法&#xff1a; 将模板名称前面加上[Item] 之后就可以正常导入笔记模板了~

Node.js -- 包管理工具

文章目录 1. 概念介绍2. npm2.1 npm 下载2.2 npm 初始化包2.3 npm 包(1) npm 搜索包(2) npm 下载安装包(3) require 导入npm 包的基本流程 2.4 开发依赖和生产依赖2.5 npm 全局安装(1) 修改windows 执行策略(2) 环境变量Path 2.6 安装包依赖2.7 安装指定版本的包2.8 删除依赖2.…