目录
- 前言
- 一、栈的介绍
- 二、数据类型重定义
- 三、栈的结构
- 四、栈中的常见操作
- 五、测试栈
- 六、栈的常见面试题
前言
前面学习的线性表中包含顺序表和链表,这两种数据结构允许在任意位置进行插入和删除,那么有没有一种数据结构是不能在任意位置进行插入删除,而只允许在一边进行插入删除的呢??当然有的,这就是我们今天要学习的一种新的数据结构:栈
一、栈的介绍
栈是一种只允许在一端进行插入删除的数据结构,插入删除的一端叫做栈顶,不能进行插入删除的一端叫做栈底。
- 入栈:指在栈进行插入数据的操作。
- 出栈:指删除栈中的栈底元素的操作。
由于栈的特殊性质,所以栈的元素的出入会满足后进先出的原则。
二、数据类型重定义
通常情况下,为了能够方便的修改数据结构中存放的数据类型,我们会对数据类型进行重定义
三、栈的结构
在学习任何的数据结构的时候,最重要的首先是要了解这个数据结构的结构,既然栈是一种数据结构,那么就说明栈可以用来存储数据,所以栈的结构中一定包含一个数据域,由于栈需要不断对栈顶元素进行出栈,所以需要一个标记栈顶元素的指针,综合这两种,我们觉得数据域设置成数组能够方便的处理这个问题。由于是数组,如果是静态数组,就导致数组的容量不能变,容量太小,会导致不够,容量太大,导致空间浪费。因此,我们觉得动态数组能够方便处理以上问题。动态数组就涉及到扩容的问题,所以肯定需要一个变量来记录数组中的容量。
在上述的结构中,val表示栈的数据域,是一个动态的数组,top表示栈顶指针,能够标识栈顶元素的情况,capacity表示栈中的容量大小。
这里需要注意一个点:top能够表示栈顶元素的情况,是数组的下标,其初始状态可以是两种表示方法
- 第一种:top = 0,表示的是栈顶元素的下一个位置,即入栈时新元素插入的位置
- 第二种:top = -1,表示的是栈顶元素的位置,当栈为空的时候,显然没有栈顶元素,所以此时top = -1。
通常情况下,为了方便表示,我们会对定义的数据结构进行重定义
四、栈中的常见操作
学习数据结构的另一个核心就是学习如何对这些数据结构进行操作
- 常见函数接口的声明
在上面的声明中,我们发现函数参数中传的是栈的结构体地址,这是为啥呢?
我们知道栈的结构本质是一个结构体,所以结构体一般都是很大的,同时,我们在函数体中有时可能需要对栈中的内容进行修改,比如入栈和出栈,就需要改变栈中的内容,如果传的是栈的结构体,那么在函数的形参中我们知道是一份实参的拷贝,所以对形参的改变是不会影响实参的,那么我们考虑传结构体的地址,通过结构体的地址,函数就可以通过指针找到真正想改变的内容。
因此,传结构体的地址的好处有两个:
- 节省形参的空间
- 能够找到真正向改变的实参,从而改变实参的内容
- 常见函数接口的实现
- 栈的初始化
初始化函数是根据数据结构中的结构来实现的,我们知道栈中包含一个动态数组的指针和一个栈顶指针和一个容量,动态刚开始啥数据都没有,我们只需要对其置成空指针即可,栈顶指针指向的是栈顶元素在数组中的下标的下一个位置,即新元素入栈时所在的位置,当栈为空的时候,栈顶指针指向0,刚开始的容量就是0
- 销毁栈
销毁栈函数主要是完成对栈中申请的空间进行释放
-
入栈
入栈时一定要考虑栈是否已经满了,如果已经满了,则需要进行扩容,扩容时一定要注意原先栈中的容量是否为0(初始化状态),这种情况需要进行特殊处理。因为top表示的是栈顶元素的下一个位置,所以是先将元素入栈到top位置,再将top++。 -
出栈
出栈的本质就是删除栈顶元素,在出栈的时候一定要注意栈是否为空,当st->top>0时才可以进行删除数据,删除的时候并不是真的将该数据从内存中移除,而是将栈顶指针往前移一位即可。 -
返回栈顶元素
返回栈顶元素函数中,也要注意栈是否为空,如果栈为空,无法返回栈顶元素,这里需要注意,因为top表示的是栈顶元素的下一个位置,所以返回的是top的前一个位置的值,而不是返回top位置的值。 -
判空
当栈顶指针指向0的时候表示现在栈是空的状态,即初始化状态。 -
栈的大小
当栈为空的时候,top = 0,每次入栈的时候,top++,出栈的时候top–,所以top可以很好地表示栈的数据个数 -
栈的容量
在上面的函数定义中,我们发现每一个函数都需要对栈的结构体指针进行断言操作,这是为啥?
在函数的操作中,我们知道函数中需要通过栈的结构体指针找到栈中的内容,也就是需要对栈的结构体指针进行解引用,因此,这个结构体指针是一定不能为空的,否则就会出现空指针的解引用从而使程序崩溃。
五、测试栈
从上面的测试代码中,我们要学习栈的基本使用:先定义一个栈的结构体,再对这个栈进行初始化操作,后面再进行各种常见的操作。除此之外,我们还需要学习栈的遍历思路:需要一个循环来解决,当栈不为空时,先访问栈的栈顶元素,再出栈。
2.
六、栈的常见面试题
- 括号匹配:有效的括号
题目:
提交代码:
提交结果:
思路分析:
本题中采用构造一个栈来解决问题,遍历给定的字符串,当遇到左括号时,入栈,当遇到右括号时,出栈顶元素和此时的右括号进行匹配,如果匹配,继续向后遍历字符串,如果不匹配,则此时返回false,在遇到右括号时,此时还需要注意一个问题,如果此时栈中没有元素,也就是没有左括号与之匹配,则返回false。当遍历完字符串之后,需要检查此时栈是否为空,如果栈为空,则成功匹配,返回true,如果栈不为空,则匹配失败,返回false。