【数据结构】栈及其经典面试题详解

news/2024/11/23 5:40:38/

目录

    • 前言
    • 一、栈的介绍
    • 二、数据类型重定义
    • 三、栈的结构
    • 四、栈中的常见操作
    • 五、测试栈
    • 六、栈的常见面试题

前言

前面学习的线性表中包含顺序表和链表,这两种数据结构允许在任意位置进行插入和删除,那么有没有一种数据结构是不能在任意位置进行插入删除,而只允许在一边进行插入删除的呢??当然有的,这就是我们今天要学习的一种新的数据结构:栈

一、栈的介绍

栈是一种只允许在一端进行插入删除的数据结构,插入删除的一端叫做栈顶,不能进行插入删除的一端叫做栈底。

  • 入栈:指在栈进行插入数据的操作。
  • 出栈:指删除栈中的栈底元素的操作。
    由于栈的特殊性质,所以栈的元素的出入会满足后进先出的原则。

二、数据类型重定义

通常情况下,为了能够方便的修改数据结构中存放的数据类型,我们会对数据类型进行重定义
在这里插入图片描述

三、栈的结构

在学习任何的数据结构的时候,最重要的首先是要了解这个数据结构的结构,既然栈是一种数据结构,那么就说明栈可以用来存储数据,所以栈的结构中一定包含一个数据域,由于栈需要不断对栈顶元素进行出栈,所以需要一个标记栈顶元素的指针,综合这两种,我们觉得数据域设置成数组能够方便的处理这个问题。由于是数组,如果是静态数组,就导致数组的容量不能变,容量太小,会导致不够,容量太大,导致空间浪费。因此,我们觉得动态数组能够方便处理以上问题。动态数组就涉及到扩容的问题,所以肯定需要一个变量来记录数组中的容量。
在这里插入图片描述
在上述的结构中,val表示栈的数据域,是一个动态的数组,top表示栈顶指针,能够标识栈顶元素的情况,capacity表示栈中的容量大小。
这里需要注意一个点:top能够表示栈顶元素的情况,是数组的下标,其初始状态可以是两种表示方法

  • 第一种:top = 0,表示的是栈顶元素的下一个位置,即入栈时新元素插入的位置
  • 第二种:top = -1,表示的是栈顶元素的位置,当栈为空的时候,显然没有栈顶元素,所以此时top = -1。
    通常情况下,为了方便表示,我们会对定义的数据结构进行重定义
    在这里插入图片描述

四、栈中的常见操作

学习数据结构的另一个核心就是学习如何对这些数据结构进行操作

  1. 常见函数接口的声明
    在这里插入图片描述
    在上面的声明中,我们发现函数参数中传的是栈的结构体地址,这是为啥呢?
    我们知道栈的结构本质是一个结构体,所以结构体一般都是很大的,同时,我们在函数体中有时可能需要对栈中的内容进行修改,比如入栈和出栈,就需要改变栈中的内容,如果传的是栈的结构体,那么在函数的形参中我们知道是一份实参的拷贝,所以对形参的改变是不会影响实参的,那么我们考虑传结构体的地址,通过结构体的地址,函数就可以通过指针找到真正想改变的内容。
    因此,传结构体的地址的好处有两个:
  • 节省形参的空间
  • 能够找到真正向改变的实参,从而改变实参的内容
  1. 常见函数接口的实现
  • 栈的初始化
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/eaf41fe1eec14806a680bc01cba32f72.pn

初始化函数是根据数据结构中的结构来实现的,我们知道栈中包含一个动态数组的指针和一个栈顶指针和一个容量,动态刚开始啥数据都没有,我们只需要对其置成空指针即可,栈顶指针指向的是栈顶元素在数组中的下标的下一个位置,即新元素入栈时所在的位置,当栈为空的时候,栈顶指针指向0,刚开始的容量就是0

  • 销毁栈
    在这里插入图片描述

销毁栈函数主要是完成对栈中申请的空间进行释放

  • 入栈
    在这里插入图片描述
    入栈时一定要考虑栈是否已经满了,如果已经满了,则需要进行扩容,扩容时一定要注意原先栈中的容量是否为0(初始化状态),这种情况需要进行特殊处理。因为top表示的是栈顶元素的下一个位置,所以是先将元素入栈到top位置,再将top++。

  • 出栈
    在这里插入图片描述
    出栈的本质就是删除栈顶元素,在出栈的时候一定要注意栈是否为空,当st->top>0时才可以进行删除数据,删除的时候并不是真的将该数据从内存中移除,而是将栈顶指针往前移一位即可。

  • 返回栈顶元素
    在这里插入图片描述
    返回栈顶元素函数中,也要注意栈是否为空,如果栈为空,无法返回栈顶元素,这里需要注意,因为top表示的是栈顶元素的下一个位置,所以返回的是top的前一个位置的值,而不是返回top位置的值。

  • 判空
    在这里插入图片描述
    当栈顶指针指向0的时候表示现在栈是空的状态,即初始化状态。

  • 栈的大小
    在这里插入图片描述
    当栈为空的时候,top = 0,每次入栈的时候,top++,出栈的时候top–,所以top可以很好地表示栈的数据个数

  • 栈的容量
    在这里插入图片描述


在上面的函数定义中,我们发现每一个函数都需要对栈的结构体指针进行断言操作,这是为啥?
在函数的操作中,我们知道函数中需要通过栈的结构体指针找到栈中的内容,也就是需要对栈的结构体指针进行解引用,因此,这个结构体指针是一定不能为空的,否则就会出现空指针的解引用从而使程序崩溃。

五、测试栈

在这里插入图片描述
从上面的测试代码中,我们要学习栈的基本使用:先定义一个栈的结构体,再对这个栈进行初始化操作,后面再进行各种常见的操作。除此之外,我们还需要学习栈的遍历思路:需要一个循环来解决,当栈不为空时,先访问栈的栈顶元素,再出栈。
2.
在这里插入图片描述

六、栈的常见面试题

  1. 括号匹配:有效的括号
    题目:
    在这里插入图片描述

提交代码:
在这里插入图片描述

提交结果:
在这里插入图片描述

思路分析:
本题中采用构造一个栈来解决问题,遍历给定的字符串,当遇到左括号时,入栈,当遇到右括号时,出栈顶元素和此时的右括号进行匹配,如果匹配,继续向后遍历字符串,如果不匹配,则此时返回false,在遇到右括号时,此时还需要注意一个问题,如果此时栈中没有元素,也就是没有左括号与之匹配,则返回false。当遍历完字符串之后,需要检查此时栈是否为空,如果栈为空,则成功匹配,返回true,如果栈不为空,则匹配失败,返回false。


http://www.ppmy.cn/news/11229.html

相关文章

SpringBoot在使用测试的时候是否需要@RunWith?

我们在使用SpringBoot进行测试的时候一般是需要加两个注解: SpringBootTest 目的是加载ApplicationContext,启动spring容器。 RunWith 是一个测试启动器,可以加载SpringBoot测试注解让测试在Spring容器环境下执行。如测试类中无此注解&#…

linux篇【13】:网络应用层—网络版计算器,序列化

目录 一.应用层 1.再谈 "协议" 2.序列化,反序列化 (1)序列化,反序列化的实例: (2)自描述长度的协议 3.网络版计算器 细节(1):报头方案 &am…

memcached面试专题及答案【三】

memcached 能接受的 key 的最大长度是多少?key 的最大长度是 250 个字符。需要注意的是,250 是 memcached 服务器端内部的限制,如果您使用的客户端支持”key 的前缀”或类似特性,那么 key(前缀原始 key)的最…

Vue 2 即将成为过去

自从 2020 年 9 月 18 日 Vue 3 正式发布以来,已经有两年多时间了,终于在 2022 年 2 月 7 日 Vue 作者发布了一则消息:Vue 3 将成为新的默认版本。与此同时,Vue 相关官方周边的核心库 latest 发布标签将指向其 Vue 3 的兼容版本。…

Springboot使用策略模式实现数据插入不同类型数据库

需求:前端会传来一些图片数据,比如图片名称,图片长宽、大小等。后端需要根据实际情况存入mysql、oracle、clickhouse等不同的数据库。 上面的需求是一个非常好的使用策略模式实现的例子。 Mapper层 定义一个顶级接口,主要定义操…

MySQL的行锁总结

文章目录前言一、行锁的介绍二、行锁的使用三、使用行锁所带来的问题四、死锁和死锁检测前言 上篇文章已经学习了MySQL的全局锁和表锁,今天这篇文章我们对行锁进行以下学习 一、行锁的介绍 行锁就是针对数据表中行记录的锁,比如事务A更新了一行&#x…

在线阅读网站|基于Springboot+Vue开发实现小说阅读网站

作者主页:编程指南针 作者简介:Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容:Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 收藏点赞不迷路 关注作者有好处 文末获取源…

Java基础学习笔记(十二)—— 数据结构

数据结构1 栈2 队列3 数组4 链表5 二叉树5.1 二叉树5.2 二叉查找树5.3 平衡二叉树5.4 红黑树6 哈希表数据结构是计算机存储、组织数据的方式。是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。…