数据结构:栈

简介: 数据结构:栈

1.栈简介


:也称为堆栈。一种线性表数据结构,是一种只允许在表的一端进行插入和删除操作的线


性表。


把栈中允许插入和删除的一端称为「栈顶(top)」;另一端则称为「栈底(bottom)」。当表


中没有任何数据元素时,称之为「空栈」


堆栈有两种基本操作:「插入操作」「删除操作」


  • 栈的插入操作又称为「入栈」或者「进栈」


  • 栈的删除操作又称为「出栈」或者「退栈」


f64755221a357c1de60060309ce220dc_2aa5df2d21a7b082da5865eebbf6e009.png

栈是一种「后进先出(Last In First Out)」的线性表,简称为 「LIFO 结构」


根据堆栈的定义,每次删除的总是堆栈中当前的栈顶元素,即最后进入堆栈的元素。而在进栈时,最先


进入堆栈的元素一定在栈底,最后进入堆栈的元素一定在栈顶。


2.栈的基本操作


栈的基本操作如下:


  • 初始化空栈:创建一个空栈,定义栈的大小 size,以及栈顶元素指针 top。


  1. 判断栈是否为空:当堆栈为空时,返回 True。当堆栈不为空时,返回 False。一般只用于栈中删除


操作和获取当前栈顶元素操作中。


  • 判断栈是否已满:当堆栈已满时,返回 True,当堆栈未满时,返回 False。一般只用于顺序栈中插


入元素和获取当前栈顶元素操作中。


  • 插入元素(进栈、入栈):相当于在线性表最后元素后面插入一个新的数据元素。并改变栈顶指针


top 的指向位置。


  • 删除元素(出栈、退栈):相当于在线性表最后元素后面删除最后一个数据元素。并改变栈顶指针


top 的指向位置。


  • 获取栈顶元素:相当于获取线性表中最后一个数据元素。与插入元素、删除元素不同的是,该操作


并不改变栈顶指针 top 的指向位置。


3.栈的顺序存储与链式存储


和线性表类似,栈有两种存储表示方法:「顺序栈」「链式栈」。


  • 「顺序栈」:即堆栈的顺序存储结构。利用一组地址连续的存储单元依次存放自栈底到栈顶的元素,


同时使用指针 top 指示栈顶元素在顺序栈中的位置。


  • 「链式栈」:即堆栈的链式存储结构。利用单链表的方式来实现堆栈。栈中元素按照插入顺序依次


插入到链表的第一个节点之前,并使用栈顶指针 top 指示栈顶元素,top 永远指向链表的头节点位


置。


3.1栈的顺序存储


栈最简单的实现方式就是借助于一个数组来描述堆栈的顺序存储结构。在 Python 中我们可以借助列


表 list 来实现。这种采用顺序存储结构的堆栈也被称为「顺序栈」。

7cee7020f6e9b2a22ab8fa181fb190d3_e9518ba4767451c5c5a8c2c6564d58e6.png


3.1.1栈的顺序存储基本描述


约定 self.top 指向栈顶元素所在位置。


  • 初始化空栈:使用列表创建一个空栈,定义栈的大小 self.size,并令栈顶元素指针 self.top 指向 -1,


即 self.top = -1。


  • 判断栈是否为空:当 self.top == -1 时,说明堆栈为空,返回 True,否则返回 False。


  • 判断栈是否已满:当 self.top == self.size - 1,说明堆栈已满,返回 True,否则返回返回 False。


  • 获取栈顶元素:先判断堆栈是否为空,为空直接抛出异常。不为空则返回 self.top 指向的栈顶元素,


即 self.stack[self.top]。


  1. 插入元素(进栈、入栈):先判断堆栈是否已满,已满直接抛出异常。如果堆栈未满,则在


self.stack 末尾插入新的数据元素,并令 self.top 向右移动 1 位。


  • 删除元素(出栈、退栈):先判断堆栈是否为空,为空直接抛出异常。如果堆栈不为空,则先让


self.top 向左移动 1 位,然后再删除当前堆栈元素。


3.1.2栈的顺序存储实现代码


class stack:
    #初始化空栈
    def _init_( self, size=100 ) :
        self.stack = [ ]
        self.size = size
        self.top = -1
    #判断栈是否为空
    def is_empty ( self ) :
        return self.top ==-1
    #判断栈是否已满
    def is_full( self ):
        return self.top + 1 == self.size
    #入栈操作
    def push ( self, value ) :
        if self.is_full( ) :
            raise Exception ( ' stack is full')
        else:
            self.stack.append ( value)
            self.top += 1
    #出栈操作
    def pop( self ):
        if self.is_empty ( ):
            raise Exception ( ' stack is empty ' )
        else:
            self.top -= 1
            self.stack.pop ()
    #获取栈顶元素
    def peek ( self ) :
        if self.is_empty ( ):
            raise Exception ( ' stack is empty ' )
        else:
            return self.stack [ self.top ]


3.2栈的链式存储


堆栈的顺序存储结构保留着顺序存储分配空间的固有缺陷,即在栈满或者其他需要重新调整存储空间时


需要移动大量元素。为此,堆栈可以采用链式存储方式来实现。在 Python 中我们通过构造链表节点


Node 的方式来实现。这种采用链式存储结构的堆栈也被称为「链式栈」。

6e35e9103a3cba613c8ddb8334b78a97_82a7c77a509705b6a5fe33ac16771a0b.png


3.2.1栈的链式存储基本描述


约定 self.top 指向栈顶元素所在节点。


  • 初始化空栈:使用链表创建一个空栈,并令栈顶元素指针 self.top 指向 None,即 self.top =


None。


  • 判断栈是否为空:当 self.top == None 时,说明堆栈为空,返回 True,否则返回 False。


  • 获取栈顶元素:先判断堆栈是否为空,为空直接抛出异常。不为空则返回 self.top 指向的栈顶节点


值,即 self.top.value。


  • 插入元素(进栈、入栈):创建值为 value 的链表节点,插入到链表头节点之前,并令栈顶指针


self.top 指向新的头节点。


  • 删除元素(出栈、退栈):先判断队列是否为空,为空直接抛出异常。如果堆栈不为空,则令


self.top 链表移动 1 位,并返回 self.top.value。


3.2.2栈的链式存储实现代码


class Node:
    def _init__( self, value) :
        self.value = value
        self.next = None
class stack :
    #初始化空栈
    def __init__(self):
        self.top = None
    #判断栈是否为空
    def is_empty ( self ) :
        return self.top ==None
    #入栈操作
    def push ( self, value ) :
        cur = Node ( value)
        cur.next = self.top
        self.top = cur
    #出栈操作
    def pop(self ):
        if self.is_empty ( ) :
            raise Exception ( ' stack is empty ' )
        else:
            cur = self.top
            self.top = self.top.next
            del cur
    #获取栈顶元素
    def peek (self ) :
        if self.is_empty ( ):
            raise Exception ( ' stack is empty ' )
        else:
            return self.top.value


4.栈的应用


栈基本应用于两个方面:


(1)使用栈可以很方便的保存和取用信息,因此常被用作算法和程序中的辅助存储结构,临时保存信息,供后面操作中使用。


例如:操作系统中的函数调用栈,浏览器中的前进、后退功能。


(2)堆栈的后进先出规则,可以保证特定的存取顺序。


例如:翻转一组元素的顺序、铁路列车车辆调度。


目录
相关文章
|
4天前
|
算法 安全 测试技术
golang 栈数据结构的实现和应用
本文详细介绍了“栈”这一数据结构的特点,并用Golang实现栈。栈是一种FILO(First In Last Out,即先进后出或后进先出)的数据结构。文章展示了如何用slice和链表来实现栈,并通过golang benchmark测试了二者的性能差异。此外,还提供了几个使用栈结构解决的实际算法问题示例,如有效的括号匹配等。
golang 栈数据结构的实现和应用
01_设计一个有getMin功能的栈
01_设计一个有getMin功能的栈
|
4天前
|
前端开发
07_用队列实现栈
07_用队列实现栈
06_用栈来求解汉诺塔问题
06_用栈来求解汉诺塔问题
05_用一个栈实现另一个栈的排序
05_用一个栈实现另一个栈的排序
03_如何仅用递归函数和栈操作逆序一个栈
03_如何仅用递归函数和栈操作逆序一个栈
|
4天前
|
测试技术
02_由两个栈组成的队列
02_由两个栈组成的队列
|
7天前
|
存储
|
22天前
|
存储 人工智能 C语言
数据结构基础详解(C语言): 栈的括号匹配(实战)与栈的表达式求值&&特殊矩阵的压缩存储
本文首先介绍了栈的应用之一——括号匹配,利用栈的特性实现左右括号的匹配检测。接着详细描述了南京理工大学的一道编程题,要求判断输入字符串中的括号是否正确匹配,并给出了完整的代码示例。此外,还探讨了栈在表达式求值中的应用,包括中缀、后缀和前缀表达式的转换与计算方法。最后,文章介绍了矩阵的压缩存储技术,涵盖对称矩阵、三角矩阵及稀疏矩阵的不同压缩存储策略,提高存储效率。
|
24天前
|
存储 C语言
数据结构基础详解(C语言): 栈与队列的详解附完整代码
栈是一种仅允许在一端进行插入和删除操作的线性表,常用于解决括号匹配、函数调用等问题。栈分为顺序栈和链栈,顺序栈使用数组存储,链栈基于单链表实现。栈的主要操作包括初始化、销毁、入栈、出栈等。栈的应用广泛,如表达式求值、递归等场景。栈的顺序存储结构由数组和栈顶指针构成,链栈则基于单链表的头插法实现。
150 3