我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python数据结构的栈实例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python数据结构的栈实例分析

这篇文章主要介绍“Python数据结构的栈实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Python数据结构的栈实例分析”文章能帮助大家解决问题。

1. 栈的基本概念

1.1 栈的基本概念

栈 (Stack) 是限定仅在序列一端执行插入和删除操作的线性表,对于栈而言,可进行操作的一端称为栈顶 (top),而另一端称为栈底 (bottom)。如果栈中不含任何元素则称其为空栈。

栈提供了一种基于在集合中的时间来排序的方式,最近添加的元素靠近顶端,旧元素则靠近底端。最新添加的元素被最先移除,这种排序原则也称为后进先出 (last in first out, LIFO) 或先进后出 (fast in last out, FILO)。

栈在现实中的例子随处可见,如下图所示,球桶中的球构成了一个栈,每次只能从顶部取出一个,放回时也只能置于顶部。假设栈为S = ( a0 , a1 , … , en)为栈顶元素,栈中元素按的顺序入栈 (push),而栈顶元素是第一个退栈 (pop) 的元素。

Python数据结构的栈实例分析

通过观察元素的添加和移除顺序,就可以快速理解栈所蕴含的思想。下图展示了栈的入栈和出栈过程,栈中元素的插入顺序和移除顺序恰好是相反的。

Python数据结构的栈实例分析

1.2 栈抽象数据类型

除了主要的操作(入栈和出栈)外,栈还具有初始化、判空和取栈顶元素等辅助操作。具体而言,栈的抽象数据类型定义如下:

Python数据结构的栈实例分析

基本操作:

__itit__(): 初始化栈

创建一个空栈

size(): 求取并返回栈中所含元素的个数 n

若栈为空,则返回整数0

isempty(): 判断是否为空栈

判断栈中是否存储元素

push(data): 入栈

将元素 data 插入栈顶

pop(): 出栈

删除并返回栈顶元素

peek(): 取栈顶元素

返回栈顶元素值,但并不删除元素

1.3 栈的应用场景

栈具有广泛的应用场景,例如:

  • 符号的匹配,具体描述参考第3.3小节;

  • 函数调用,每个未结束调用的函数都会在函数栈中拥有一块数据区,保存了函数的重要信息,包括函数的局部变量、参数等;

  • 后缀表达式求值,计算后缀表达式只需一个用于存放数值的栈,遍历表达式遇到数值则入栈,遇到运算符则出栈两个数值进行计算,并将计算结果入栈,最后栈中保留的唯一值即为表达式结果;

  • 网页浏览中的返回按钮,当我们在网页间进行跳转时,这些网址都被存放在一个栈中;

  • 编辑器中的撤销序列,与网页浏览中的返回按钮类似,栈保存每步的编辑操作。

除了以上应用外,我们在之后的学习中还将看到栈用作许多算法的辅助数据结构。

2. 栈的实现

和线性表一样,栈同样有两种存储表示方式。

2.1 顺序栈的实现

顺序栈是栈的顺序存储结构,其利用一组地址连续的存储单元从栈底到栈顶依次存放。同时使用指针top来指示栈顶元素在顺序栈中的索引,同样顺序栈可以是固定长度和动态长度,当栈满时,定长顺序栈会抛出栈满异常,动态顺序栈则会动态申请空闲空间。

2.1.1 栈的初始化

顺序栈的初始化需要三部分信息:stack 列表用于存储数据元素,max_size 用于存储 stack 列表的最大长度,以及 top 用于记录栈顶元素的索引:

class Stack:    def __init__(self, max_size=10):        self.max_size = max_size        self.stack = self.max_size * [None]        self.top = -1

1.2 求栈长

由于 top 表示栈顶元素的索引,我们可以据此方便的计算顺序栈中的数据元素数量,即栈长:

    def size(self):        return self.top + 1

1.3 判栈空

根据栈的长度可以很容易的判断栈是否为空栈:

    def isempty(self):        if self.size() == 0:            return True        else:            return False

1.4 判栈满

由于需要提前申请栈空间,因此我们需要能够判断栈是否还有空闲空间:

    def isfully(self):        if self.size() == self.max_size:            return True        else:            return False

1.5 入栈

入栈时,需要首先判断栈中是否还有空闲空间,然后根据栈为定长顺序栈或动态顺序栈,入栈操作稍有不同:

[定长顺序栈的入栈操作] 如果栈满,则引发异常:

    def push(self, data):        if self.isfully():            raise IndexError('Stack Overflow!')        else:            self.top += 1            self.stack[self.top_1] = data

[动态顺序栈的入栈操作] 如果栈满,则首先申请新空间:

    def resize(self):        new_size = 2 * self.max_size        new_stack = [None] * new_size        for i in range(self.num_items):            new_stack[i] = self.items[i]        self.stack = new_stack        self.max_size = new_size    def push(self, data):        if self.isfully():            self.resize()        else:            self.top += 1            self.stack[self.top_1] = data

入栈的时间复杂度为O(1)。这里需要注意的是,虽然当动态顺序栈满时,原栈中的元素需要首先复制到新栈中,然后添加新元素,但根据《顺序表及其操作实现》中顺序表追加操作的介绍,由于n次入栈操作的总时间T(n) 与O(n) 成正比,因此入栈的摊销时间复杂度仍可以认为是O(1)。

1.6 出栈

若栈不空,则删除并返回栈顶元素:

    def pop(self):        if self.isempty():            raise IndexError('Stack Underflow!')        else:            result = self.stack[self.top]            self.top -= 1            return result

1.7 求栈顶元素

若栈不空,则只需返回栈顶元素:

    def peek(self):        if self.isempty():            raise IndexError('Stack Underflow!')        else:            return self.stack[self.top]

2.2 链栈的实现

栈的另一种存储表示方式是使用链式存储结构,因此也常称为链栈,其中 push 操作是通过在链表头部插入元素来实现的,pop 操作是通过从头部删除节点来实现的。

2.1 栈结点

栈的结点实现与链表并无差别:

class Node:    def __init__(self, data):        self.data = data        self.next = None    def __str__(self):        return str(self.data)

2.2 栈的初始化

栈的初始化函数中,使栈顶指针指向 None,并初始化栈长:

class Stack:    def __init__(self):        self.top = None        # 栈中元素数        self.length = 0

2.3 求栈长

返回 length 的值用于求取栈的长度,如果没有 length 属性,则需要遍历整个链表才能得到栈长:

    def size(self):        return self.length

2.4 判栈空

根据栈的长度可以很容易的判断栈是否为空栈:

    def isempty(self):        if self.length == 0:            return True        else:            return False

2.5 入栈

入栈时,在栈顶插入新元素即可:

    def push(self, data):        p = Node(data)        p.next = self.top        self.top = p        self.length += 1

由于插入元素是在链表头部进行的,因此入栈的时间复杂度为O(1),在这种情况下链尾作为栈底 。

2.5 出栈

若栈不空,则删除并返回栈顶元素:

    def pop(self):        if self.isempty():            raise IndexError("Stack Underflow!")        ele = self.top.data        self.top = self.top.next        self.length -= 1        return ele

由于删除元素仅需修改头指针指向其 next 域,因此出栈的时间复杂度同样为O(1)。

2.6 求栈顶元素

若栈不空,返回栈顶元素即可,但栈顶元素并不会被删除:

    def peek(self):        if self.isempty():            raise IndexError("Stack Underflow!")        return self.top.data

2.3 栈的不同实现对比

本节我们将对比栈的不同实现之间的异同:

顺序栈

  • 操作的时间复杂度均为O(1),列表的尾部作为栈顶

  • 栈满时需要进行动态的扩展,复制原栈元素到新栈中

链栈

  • 操作的时间复杂度均为O(1),链表的头部作为栈顶

  • 优雅的扩展,无需考虑栈满,需要额外的空间存储指针

3. 栈应用

接下来,我们首先测试上述实现的链表,以验证操作的有效性,然后利用实现的基本操作来解决实际算法问题。

3.1 顺序栈的应用

首先初始化一个顺序栈 stack,然后测试相关操作:

# 初始化一个最大长度为4的栈s = Stack(4)print('栈空?', s.isempty())for i in range(4):    print('入栈元素:', i)    s.push(i)print('栈满?', s.isfully())print('栈顶元素:', s.peek())print('栈长度为:', s.size())while not s.isempty():    print('出栈元素:', s.pop())

测试程序输出结果如下:

栈空? True
入栈元素: 0
入栈元素: 1
入栈元素: 2
入栈元素: 3
栈满? True
栈顶元素: 3
栈长度为: 4
出栈元素: 3
出栈元素: 2
出栈元素: 1
出栈元素: 0

3.2 链栈的应用

首先初始化一个链栈 stack,然后测试相关操作:

# 初始化新栈s = Stack()print('栈空?', s.isempty())for i in range(4):    print('入栈元素:', i)    s.push(i)print('栈顶元素:', s.peek())print('栈长度为:', s.size())while not s.isempty():    print('出栈元素:', s.pop())

测试程序输出结果如下:

栈空? True
入栈元素: 0
入栈元素: 1
入栈元素: 2
入栈元素: 3
栈顶元素: 3
栈长度为: 4
出栈元素: 3
出栈元素: 2
出栈元素: 1
出栈元素: 0

3.3 利用栈基本操作实现复杂算法

匹配符号是指正确地匹配左右对应的符号(符号允许进行嵌套),不仅每一个左符号都有一个右符号与之对应,而且两个符号的类型也是一致的,下标展示了一些符号串的匹配情况:

符号串是否匹配
[]()()匹配
[(())()不匹配
{([]())}匹配
(())[]}不匹配

为了检查符号串的匹配情况,需要遍历符号串,如果字符是 (、[ 或 { 之类的开始分隔符,则将其写入栈中;当遇到诸如 )、] 或 } 等结束分隔符时,则栈顶元素出栈,并将其与当前遍历元素进行比较,如果它们匹配,则继续解析符号串,否则表示不匹配。当遍历完成后,如果栈不为空,则同样表示不匹配:

def isvalid_expression(expression):    stack = Stack()    symbols = {')':'(', ']':'[', '}':'{'}    for s in expression:        if s in symbols:            if stack:                top_element = stack.pop()            else:                top_element = '#'            if symbols[s] != top_element:                return False        else:            stack.push(s)    return not stack

由于我们只需要遍历符号串一边,因此算法的时间复杂度为O(n),算法的空间复杂度同样为O(n)。

给定一链表(带有头结点) L : L0→L1→…→Ln ,将其重排为:L0→Ln→L1→Ln−1 … 。

例如链表中包含 9 个元素,则下图现实了重排前后的链表元素情况:

Python数据结构的栈实例分析

由于栈的先进后出原则,可以利用栈与原链表的配合进行重排,首次按遍历链表,将每个结点入栈;栈中元素的出栈顺序为原链表结点的逆序,然后交替遍历链表和栈,构建新链表。

def reorder_list(L):    p = L.head.next    if p == None:        return L    stack = Stack()    while p!= None:        stack.push(p)        p = p.next    l = L.head.next    from_head = L.head.next    from_stack = True    while (from_stack and l != stack.peek() or (not from_stack and l != from_head)):        if from_stack:            from_head = from_head.next            l.next = stack.pop()            from_stack = False        else:            l.next = from_head            from_stack = True        l = l.next    l.next = None

该算法的时间复杂度和空间复杂度均为O(n)。

关于“Python数据结构的栈实例分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网行业资讯频道,小编每天都会为大家更新不同的知识点。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Python数据结构的栈实例分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python数据结构的栈实例分析

这篇文章主要介绍“Python数据结构的栈实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Python数据结构的栈实例分析”文章能帮助大家解决问题。1. 栈的基本概念1.1 栈的基本概念栈 (
2023-06-29

C++数据结构的栈与队列实例分析

今天小编给大家分享一下C++数据结构的栈与队列实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1. 栈1.1 栈的概念
2023-06-30

JavaScript数据结构与算法之栈实例分析

这篇文章主要介绍了JavaScript数据结构与算法之栈实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JavaScript数据结构与算法之栈实例分析文章都会有所收获,下面我们一起来看看吧。1.认识栈栈:
2023-07-02

Python Pandas中的数据结构实例分析

今天小编给大家分享一下Python Pandas中的数据结构实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。前言:Pa
2023-07-02

Python 数据结构之堆栈实例代码

Python 堆栈 堆栈是一个后进先出(LIFO)的数据结构. 堆栈这个数据结构可以用于处理大部分具有后进先出的特性的程序流 . 在堆栈中, push 和 pop 是常用术语:push: 意思是把一个对象入栈.pop: 意思是把一个对象出
2022-06-04

C++数据结构关于栈迷宫示例分析

这篇文章主要讲解了“C++数据结构关于栈迷宫示例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++数据结构关于栈迷宫示例分析”吧!一、实验目的理解栈的抽象数据类型定义及操作特点。掌握顺
2023-06-21

python数据结构堆的示例分析

小编给大家分享一下python数据结构堆的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!1、说明堆是用数据结构来实现的一种算法:树,数组均可。堆本身是一棵完全二叉树。2、特点最大堆:所有父节点的值大于子节点的值最小
2023-06-15

Python Pandas数据结构的示例分析

这篇文章将为大家详细讲解有关Python Pandas数据结构的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1 Pandas介绍2008年WesMcKinney开发出的库专门用于数据挖掘的开源p
2023-06-29

JavaScript数据结构Number实例分析

本文小编为大家详细介绍“JavaScript数据结构Number实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“JavaScript数据结构Number实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧
2023-06-29

用Python实现数据结构之栈

栈是最简单的数据结构,也是最重要的数据结构。它的原则就是后进先出(LIFO),栈被使用于非常多的地方,例如浏览器中的后退按钮,文本编辑器中的撤销机制,接下来我们用Python来具体实现这个数据结构。栈中的方法作为一个栈(用S来表示),最基本
2023-01-30

python数据结构算法的示例分析

小编给大家分享一下python数据结构算法的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1.算法分析的定义有这样一个问题:当两个看上去不同的程序 解决同
2023-06-22

Python数据结构创建的示例分析

本篇文章为大家展示了Python数据结构创建的示例分析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1. 列表list:变量赋值方式:shoplist = [apple, mango, carrot
2023-06-17

基于C++的数据结构实例分析

本篇内容介绍了“基于C++的数据结构实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!数据结构通常情况下,精心选择的数据结构可以带来更高
2023-07-02

Python实现基本数据结构中栈的操作示例

本文实例讲述了Python实现基本数据结构中栈的操作。分享给大家供大家参考,具体如下:#! /usr/bin/env python #coding=utf-8 #Python实现基本数据结构---栈操作 class Stack(object
2022-06-04

Python高级数据结构与算法实例分析

本文小编为大家详细介绍“Python高级数据结构与算法实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python高级数据结构与算法实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、简介我们将从以
2023-07-05

Python数据结构之栈、队列的实现代码分享

1. 栈 栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶
2022-06-04

Python不可变数据结构举例分析

这篇文章主要讲解了“Python不可变数据结构举例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python不可变数据结构举例分析”吧!我们从思考正方形和矩形开始。如果我们抛开实现细节,
2023-06-17

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录