数据结构入门:栈

目录

前言

1. 栈

1.1栈的概念及结构

 1.2 栈的实现

1.2.1 栈的定义

 1.2.2  栈的初始化

1.2.3 入栈

1.2.4 出栈

1.2.5  栈的元素个数

1.2.6 栈顶数据

1.2.7 栈的判空

 2.栈的应用

 2.1 题目一:括号匹配

2.1.1 思路

 2.1.2 分析

 2.1.3 题解

总结


前言

        无论你是计算机科学专业的学生、程序设计的爱好者,还是正在准备面试的求职者,本文将为你提供一份全面而深入的栈和队列指南。让我们一起探索栈和队列的双重魅力,为你的编程之路增添新的色彩。


1. 栈

1.1栈的概念及结构

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

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

  • 压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
  • 出栈:栈的删除操作叫做出栈。出数据也在栈顶。

 

 1.2 栈的实现

        栈的实现方法有两种,一种是顺序表的栈,另外一种就是链表实现的栈。相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小,所以这里我们使用顺序表来实现栈。

         如果熟练顺序表和链表操作,那栈就会相当轻松,栈的入栈出栈就相当于是尾插尾删,顺序表尾插尾删的效率高,这也是使用顺序表实现的原因。

1.2.1 栈的定义

首先我们需要先定义一个栈:

typedef int Datatype;
typedef struct Stack
{Datatype* a;int top;int capacity;
}Stack;

 栈中有栈顶(top),有栈的容量(size),还有存储的数据(a);

 1.2.2  栈的初始化

 

void InItStack(Stack* ps)
{assert(ps);ps->top = 0;ps->a = NULL;ps->capacity = 0;
}

         这里对栈进行初始化时栈顶(top)可以置为-1,也可以置为0,置为0为了便于使用top作为数组下标插入数据。

1.2.3 入栈

        栈已经定义完成并且进行了初始化,接下来就是入栈操作。这里与顺序表的尾插略微有些不同。

void StackPush(Stack* ps, Datatype x)
{assert(ps);if (ps->top == ps->capacity){int newcapacity = (ps->capacity == 0 ? 4 : ps->capacity * 2);Datatype* tmp = (Datatype*)realloc(ps->a, sizeof(Datatype) * newcapacity);if (tmp == NULL){perror("realloc fail");exit(-1);}ps->a = tmp;ps->capacity = newcapacity;}ps->a[ps->top] = x;//top初始化为0,可以直接作为数组下标ps->top++;//入栈后top++,便于统计元素个数和下次入栈
}

        由于我们初始化时将栈的容量置为0,在这里我们在入栈操作时就需要进行开辟空间,但这里如果我们使用malloc开辟空间,就还需要进行扩容操作,所以我们直接使用realloc进行开辟空间。

 realloc在扩容时,如果原始区域空间为0,那么它的作用就类似于malloc。

         此外我们还需要有新开辟空间的大小,这里我们直接使用一个判断语句:newsize = (ps->size == 0 ? 4 : ps->size * 2);  如果size等于0就开辟4个存储数据的空间,如果不等于0就直接扩容为2倍。

1.2.4 出栈

 出栈操作就很简单了,也不需要销毁,直接进行top--:

void StackPop(Stack* ps)
{assert(ps);assert(ps->top > 0);ps->top--;
}

        但我们需要注意栈为空的情况,所有使用assert强制检查,如果为空直接报错终止程序,简单粗暴。

1.2.5  栈的元素个数

统计栈的元素个数接口也很简单,top就是栈中元素的个数

int Stacksize(Stack* ps)
{assert(ps);return ps->top;
}

1.2.6 栈顶数据

Datatype TopData(Stack* ps)
{assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1];
}

这个也非常简单,需要注意栈为空的情况。

1.2.7 栈的判空

bool IsEmpty(Stack* ps)
{assert(ps);return (ps->top == 0);
}

 2.栈的应用

         这些栈的基本操作我们已经实现了,接下来我们来实际应用一下。虽然栈的基本操作更为简单,但是栈在应用时数据的结构更加复杂,前边的顺序表和链表是栈和队列的基础。

 2.1 题目一:括号匹配

        这道题目我们可以使用数组实现并解决,但我们已经了解了栈,这道题目我们就使用顺序表栈来实现。我们可以直接复制上述栈基本操作的代码。将 typedef  int  Datatype;

 改为:typedef  char  Datatype;

题目描述:

 示例:

 题目链接:

有效括号

2.1.1 思路

         这道题目的思路很明确,入栈左括号,遇到匹配的右括号就出栈。如果最终栈为空就匹配成功。但匹配失败的情况有很多,接下来我们进行逐个分析。

 2.1.2 分析

         首先是入栈,如果为左括号就入栈,为右括号就匹配出栈。这里使用if…else语句更为简洁,入栈就需要我们调用入栈的函数接口。

        其次就是匹配、出栈。但在匹配之前我们还需要考虑特殊情况,就是如果没有出栈元素就直接匹配的情况,所以首先我们需要有一个判空操作,如果匹配时栈就为空就直接匹配失败,并销毁栈,这个属于左括号与右括号数量匹配失败。

         接着就是顺序匹配失败,这里就需要我们用到栈顶元素了,如果栈顶元素与匹配的括号不匹配就直接返回false,匹配失败,销毁栈。

        最后,匹配结束,存放括号数组为空,栈也为空就匹配成功。

 2.1.3 题解

匹配括号接口:

bool isValid(char* s) {Stack st;InItStack(&st);char top;while (*s){if (*s == '(' || *s == '[' || *s == '{'){StackPush(&st, *s);}else{if(IsEmpty(&st)){DestoryStack(&st);return false;}top=TopData(&st);StackPop(&st);if((*s==']'&&top!='[')||(*s==')'&&top!='(')||(*s=='}'&&top!='{')){DestoryStack(&st);return false;}}s++;}bool ret = IsEmpty(&st);DestoryStack(&st);return ret;
}

整体代码:

typedef char Datatype;
typedef struct Stack
{Datatype* a;int top;int size;
}Stack;void InItStack(Stack* ps);void DestoryStack(Stack* ps);void StackPush(Stack* ps, Datatype x);void StackPop(Stack* ps);int Stacksize(Stack* ps);Datatype TopData(Stack* ps);bool IsEmpty(Stack* ps);void InItStack(Stack* ps)
{assert(ps);ps->top = 0;ps->a = NULL;ps->size = 0;
}void DestoryStack(Stack* ps)
{assert(ps);ps->top = ps->size = 0;free(ps->a);ps->a = NULL;
}
void StackPush(Stack* ps, Datatype x)
{assert(ps);if (ps->top == ps->size){int newsize = (ps->size == 0 ? 4 : ps->size * 2);Datatype* tmp = (Datatype*)realloc(ps->a, sizeof(Datatype) * newsize);if (tmp == NULL){perror("realloc fail");exit(-1);}ps->a = tmp;ps->size = newsize;}ps->a[ps->top] = x;ps->top++;
}
void StackPop(Stack* ps)
{assert(ps);assert(ps->top > 0);ps->top--;
}
int Stacksize(Stack* ps)
{assert(ps);return ps->top;
}
Datatype TopData(Stack* ps)
{assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1];
}
bool IsEmpty(Stack* ps)
{assert(ps);return (ps->top == 0);
}
bool isValid(char* s) {Stack st;InItStack(&st);char top;while (*s){if (*s == '(' || *s == '[' || *s == '{'){StackPush(&st, *s);}else{if(IsEmpty(&st)){DestoryStack(&st);return false;}top=TopData(&st);StackPop(&st);if((*s==']'&&top!='[')||(*s==')'&&top!='(')||(*s=='}'&&top!='{')){DestoryStack(&st);return false;}}s++;}bool ret = IsEmpty(&st);DestoryStack(&st);return ret;
}

         栈相对于链表和顺序表没有那么多的操作,更为简单,但在实际应用时数据结构更加复杂,但是别担心,后续学习C++后可以直接使用现成的库函数,不需要再对栈的各个操作进行实现。


  

总结

        栈是一种重要的数据结构,它以后进先出的方式操作数据。栈在递归算法、表达式求值、函数调用等场景中发挥着重要作用。通过学习栈,我们能够更好地理解数据结构的本质和算法的设计思想。栈不仅仅是一种数据存储的方式,更是一种思维方式和问题解决的工具。无论是计算机科学的学习者、程序设计的爱好者,还是正在准备面试的求职者,通过探索栈的原理和应用,我们能够提升自己的编程能力和解决问题的能力。让我们一起深入探索栈的魅力,为编程之路增添新的色彩。最后,感谢阅读!

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

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

相关文章

算法笔试 java 输入输出练习

在线编程题刷题训练 所有答案 scancer函数的用法 输入输出总结top!!!! java如何调用函数(方法) java刷acm的各种输入输出 vscode配置java环境 子函数的调用,直接定义一个static子函数调用就…

c51单片机串口通信(中断方式接收数据)(单片机--单片机通信)示例代码 附proteus图

单片机一般采用中断方式接受数据,这样便于及时处理 #include "reg51.h" #include "myheader.h" #define uchar unsigned char int szc[10]{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; int bufferc[6]{0}; int sza[6]{0x01,0x02,0x0…

46.利用matlab绘制维安尼曲线(matlab程序)

1.代码 clear close all syms s t k u r; x12*sin(s)*cos(t);y12*sin(s)*sin(t);z12*cos(s); x2-2*cos(k)*cos(k);y22*sin(k)*cos(k);z2u; subplot(1,2,1);ezmeshc(x2,y2,z2,[0,pi,-2,2]); %绘制圆柱面 hold on; ezsurf(x1,y1,z1,[-pi,pi,0,pi]); %绘制球面 title( 球面与圆柱…

Windows11中使用OneDrive按Print Screen截屏按键,把截图自动保存到OneDrive中

参考:关于Onedrive 我已经勾选了自动保存屏幕截图 但是我截图之后我的图片并没有上传到onedrive上面 - Microsoft Community 1. 打开Windows 11的设置,可以通过按下Win I键来快速打开设置; 2. 设置--辅助功能--键盘--使用”print Screen“键…

ChatGPT能代替搜索引擎吗?ChatGPT和搜索引擎有什么区别?

ChatGPT和搜索引擎是两种在信息获取和交流中常用的工具,ChatGPT是一种基于人工智能技术的聊天机器人,而搜索引擎是一种在互联网上搜索信息的工具。尽管它们都是依托互联网与信息获取和交流有关,部分功能重合,但在很多方面存在着明…

vue中封装自动计算比例滑块

此插件为另一位漂亮的前端同事小姐姐封装,觉得非常好用于是决定记载下来,便于复用 如图需要动态传入需要分配权重的数组,平均分配可以自动将100%平均分给数组中的值 如果手动拖拽,则会自动计算可拖动最大区域,便于最终总权重必定为100% <el-alert class"merge-alert&…

2023国赛数学建模D题思路分析

文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 全国大学生数学建模…

Spring Boot + Vue3前后端分离实战wiki知识库系统十二--用户管理单点登录开发一...

目标&#xff1a; 在上一次https://www.cnblogs.com/webor2006/p/17533745.html我们已经完成了文档管理的功能模块开发&#xff0c;接下来则开启新模块的学习---用户登录&#xff0c;这块还是有不少知识点值得学习的&#xff0c;先来看一下整体的效果&#xff0c;关于效果官网有…

BUUCTF 还原大师 1

题目描述&#xff1a; 我们得到了一串神秘字符串&#xff1a;TASC?O3RJMV?WDJKX?ZM,问号部分是未知大写字母&#xff0c;为了确定这个神秘字符串&#xff0c;我们通过了其他途径获得了这个字串的32位MD5码。但是我们获得它的32位MD5码也是残缺不全&#xff0c;E903???4D…

【elementUi】绘制自定义表格、绘制曲线表格

要求绘制下图系列表格&#xff1a; 实现步骤: 1.绘制树&#xff0c;实现树勾选字段—>表格绘制字段 逻辑&#xff1a; 树&#xff1a;check-change“treeChart.handleCheckChange” 绑定点击选择事件&#xff0c;改变data.column3数据项&#xff1b;表格:columns"data…

1. 基于UDP的TFTP文件传输上传下载完整版本

1&#xff09;tftp协议概述 简单文件传输协议&#xff0c;适用于在网络上进行文件传输的一套标准协议&#xff0c;使用UDP传输 特点&#xff1a; 是应用层协议 基于UDP协议实现 数据传输模式 octet&#xff1a;二进制模式&#xff08;常用&#xff09; mail&#xff1a;…

Install And Understand APISIX(Master the knowledge of APISIX)

Master the knowledge of APISIX Install And Understand APISIX 环境准备 接口服务&#xff1a;gpt 接口服务&#xff08;使用 spring boot 编写的 Chat GPT 接口服务&#xff09; 调用接口示例&#xff1a; 虚拟机软件&#xff1a;VMware Workstation Pro 17 Linux 镜像&…

大数据Flink(六十三):SqlClient工具的使用

文章目录 SqlClient工具的使用 一、​​​​​​​入门

(二分查找) 11. 旋转数组的最小数字 ——【Leetcode每日一题】

❓剑指 Offer 11. 旋转数组的最小数字 难度&#xff1a;简单 把一个数组最开始的若干个元素搬到数组的末尾&#xff0c;我们称之为数组的旋转。 给你一个可能存在 重复 元素值的数组 numbers &#xff0c;它原来是一个升序排列的数组&#xff0c;并按上述情形进行了一次旋转…

分布式唯一ID实战

目录 一、UUID二、数据库方式1、数据库生成之简单方式2、数据库生成 - 多台机器和设置步长&#xff0c;解决性能问题3、Leaf-segment 方案实现4、双 buffer 优化5、Leaf高可用容灾 三、基于Redis实现分布式ID四、雪花算法 一、UUID UUID的标准形式包含32个16进制数字&#xff…

UE5 实现残影效果

文章目录 前言实现效果示例1示例2示例3示例4实现扩展前言 本文采用虚幻5.2.1版本,对角色生成残影效果进行讲解,以一种简单的、通俗易懂的、高性能的方式来实现此效果。此效果可以在角色使用某一技能时触发,比如使用攻击招式、闪现等等。 实现效果 示例1 在昏暗的环境示例…

用 oneAPI 实现 AI 欺诈检测:一款智能图像识别工具

简介 虚假图像和视频日益成为社交媒体、新闻报道以及在线内容中的一大隐患。在这个信息爆炸的时代&#xff0c;如何准确地识别和应对这些虚假内容已经成为一个迫切的问题。为了帮助用户更好地辨别虚假内容&#xff0c;我开发了一款基于 oneAPI、TensorFlow 和 Neural Compress…

百日筑基篇——python爬虫学习(一)

百日筑基篇——python爬虫学习&#xff08;一&#xff09; 文章目录 前言一、python爬虫介绍二、URL管理器三、所需基础模块的介绍1. requests2. BeautifulSoup1. HTML介绍2. 网页解析器 四、实操1. 代码展示2. 代码解释1. 将大文件划分为小的文件&#xff08;根据AA的ID数量划…