数据结构:栈

简介: 数据结构:栈

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)堆栈的后进先出规则,可以保证特定的存取顺序。


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


目录
相关文章
|
1月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
208 9
|
1月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
35 1
|
27天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
53 5
|
1月前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。
|
1月前
|
存储 JavaScript 前端开发
执行上下文和执行栈
执行上下文是JavaScript运行代码时的环境,每个执行上下文都有自己的变量对象、作用域链和this值。执行栈用于管理函数调用,每当调用一个函数,就会在栈中添加一个新的执行上下文。
|
1月前
|
存储
系统调用处理程序在内核栈中保存了哪些上下文信息?
【10月更文挑战第29天】系统调用处理程序在内核栈中保存的这些上下文信息对于保证系统调用的正确执行和用户程序的正常恢复至关重要。通过准确地保存和恢复这些信息,操作系统能够实现用户模式和内核模式之间的无缝切换,为用户程序提供稳定、可靠的系统服务。
51 4
|
2月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
48 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
1月前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
1月前
|
算法
数据结构之购物车系统(链表和栈)
本文介绍了基于链表和栈的购物车系统的设计与实现。该系统通过命令行界面提供商品管理、购物车查看、结算等功能,支持用户便捷地管理购物清单。核心代码定义了商品、购物车商品节点和购物车的数据结构,并实现了添加、删除商品、查看购物车内容及结算等操作。算法分析显示,系统在处理小规模购物车时表现良好,但在大规模购物车操作下可能存在性能瓶颈。
49 0
|
2月前
初步认识栈和队列
初步认识栈和队列
65 10