【Python】一文带你学会数据结构中的堆、栈

news2024/11/23 9:48:07

 

作者主页:爱笑的男孩。的博客_CSDN博客-深度学习,活动,python领域博主爱笑的男孩。擅长深度学习,活动,python,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?type=blog个人简介:打工人。

持续分享:机器学习、深度学习、python相关内容、日常BUG解决方法及Windows&Linux实践小技巧。

如发现文章有误,麻烦请指出,我会及时去纠正。有其他需要可以私信我或者发我邮箱:zhilong666@foxmail.com 

        堆是一种特殊的数据结构,具有优秀的性能和灵活的应用场景。在Python中,堆可以通过内置的heapq模块来实现。栈是一种非常重要的数据结构,常被用于解决各种计算机科学问题。

本文将详细讲解Python数据结构中的堆、栈


目录

一、堆

1.1 堆的简介

1.1.1 堆的定义

1.1.2 堆的表示方法

1.1.3 堆的操作

1.2 堆的发展史

1.2.1 二叉堆

1.2.2 Fibonacci堆

1.2.3 优先队列

1.3 堆的使用方法

1.3.1 创建堆

1.3.2 插入元素

1.3.3 弹出元素

1.3.4 替换元素

1.3.5 合并堆

1.3.6 堆排序

1.4 堆的总结

二、栈

2.1 栈的简介

2.1.1 栈的定义

2.1.2 栈的特性

2.1.3 栈的应用场景

2.2 栈的发展史

2.2.1 早期栈(Early Stack)

2.2.2 数组栈(Array-Based Stack)

2.2.3 链表栈(Linked List-Based Stack)

2.2.4 动态数组栈(Dynamic Array-Based Stack)

2.3 栈的使用方法

2.3.1 初始化栈

2.3.2 压栈(入栈)

2.3.3 弹栈(出栈)

2.3.4 获取栈顶元素

2.3.5 判断栈是否为空 

2.3.6 显示栈的元素 

2.3.7 综合示例代码如下:

2.4 栈的总结

2.4.1 栈的特点:

2.4.2 基本操作:

2.4.3 栈的应用:

2.4.4 栈的实现:


一、堆

1.1 堆的简介

1.1.1 堆的定义

        堆是一种特殊的树状数据结构,它满足以下两个主要性质:

  • 堆是完全二叉树:堆中的所有层级除了最后一层都是完全填满的,最后一层的节点都靠左排列。
  • 堆的任意节点的值都不大于(或不小于)其子节点的值:这一性质称为堆属性。

        根据堆属性的不同,可以将堆分为最大堆和最小堆。

1.1.2 堆的表示方法

        在Python中,可以使用列表来表示堆。具体而言,堆的第一个元素(索引为0)为根节点,其他元素按照从上到下、从左到右的顺序排列。

1.1.3 堆的操作

        堆主要支持以下几种操作:

  • 插入:将一个新元素插入堆中,并保持堆的结构和堆属性。
  • 删除最小(或最大)值:移除堆中的根节点,并保持堆的结构和堆属性。
  • 构建堆:构建一个新的堆,将一个无序列表转换为堆的形式。

1.2 堆的发展史

        堆作为一种经典的数据结构,诞生于20世纪60年代,由艾德加·斯特恩(Edgar F. Codd)在数据库领域首次提出。后来,堆被应用于算法和数据结构的研究中,并衍生出了多种不同的使用形式。

1.2.1 二叉堆

        二叉堆是堆的最基础形式,是堆的最常用实现方式。它满足堆的定义,同时使用完全二叉树的结构。在二叉堆中,每个节点的值都不小于(或不大于)其子节点的值。

1.2.2 Fibonacci堆

        Fibonacci堆是为了解决二叉堆在某些操作上效率低下的问题而提出的。Fibonacci堆将支持由二项堆、配对堆(Pairing Heap)和斐波那契堆(Fibonacci Heap)构成的一组堆结构。与二叉堆相比,Fibonacci堆具有更好的平摊时间复杂度,但也带来了更大的常数时间。

1.2.3 优先队列

        优先队列是一种特殊的数据结构,堆是实现优先队列的常用方式之一。优先队列中的每个元素都有一个优先级,优先级高的元素排在前面。堆可以很好地支持优先队列的插入和删除操作,保持队列中的元素按照优先级有序。

1.3 堆的使用方法

        首先,我们需要导入Python的heapq模块,它是Python标准库中用于实现堆的模块。使用如下语句导入:

import heapq

        接下来,我将逐一介绍堆的基本操作。

1.3.1 创建堆

        在Python中,我们可以使用heapq模块来创建堆。可以通过heapq.heapify()函数将一个列表转换为堆。下面是一个示例:

import heapq

data = [5, 2, 8, 0, 3, 9, 1]
heapq.heapify(data)
print(data)  # 输出: [0, 2, 1, 5, 3, 9, 8]

        可以看到,通过heapify()函数,列表data被转换为了一个堆。 

1.3.2 插入元素

        要在堆中插入一个元素,可以使用heapq.heappush()函数。下面是一个示例:

import heapq

data = [5, 2, 8, 0, 3, 9, 1]
heapq.heapify(data)
heapq.heappush(data, 6)
print(data)  # 输出: [0, 2, 1, 5, 3, 9, 8, 6]

         可以看到,通过heappush()函数,元素6被插入堆中,并且堆的特性得到保持。

1.3.3 弹出元素

        要从堆中弹出最小(或最大)的元素,可以使用heapq.heappop()函数。下面是一个示例:

import heapq

data = [0, 2, 1, 5, 3, 9, 8]
heapq.heapify(data)
smallest = heapq.heappop(data)
print(smallest)  # 输出: 0
print(data)  # 输出: [1, 2, 8, 5, 3, 9]

        可以看到,通过heappop()函数,堆中的最小值0被弹出,并且堆的特性得到保持。 

1.3.4 替换元素

        替换堆中的元素与弹出元素操作类似,可以使用heapq.heapreplace()函数。下面是一个示例:

import heapq

data = [0, 2, 1, 5, 3, 9, 8]
heapq.heapify(data)
smallest = heapq.heapreplace(data, 7)
print(smallest)  # 输出: 0
print(data)  # 输出: [1, 2, 7, 5, 3, 9, 8]

        可以看到,通过heapreplace()函数,堆中的最小值0被弹出,并且被元素7替换。替换操作无需先弹出最小值再插入新元素,因此具有更高的效率。 

1.3.5 合并堆

        可以使用heapq.merge()函数合并多个堆,返回一个新的堆。下面是一个示例:

import heapq

heap1 = [1, 3, 5]
heap2 = [2, 4, 6]
merged = heapq.merge(heap1, heap2)
print(list(merged))  # 输出: [1, 2, 3, 4, 5, 6]

        可以看到,通过merge()函数,堆heap1heap2被合并成了一个新的堆。 

1.3.6 堆排序

        堆排序是利用堆的特性来对列表进行排序的一种方法。可以使用heapq模块中的heappushpop()函数和heapq.nsmallest()函数实现堆排序。下面是一个示例:

import heapq

data = [5, 2, 8, 0, 3, 9, 1]
sorted_data = [heapq.heappop(data) for _ in range(len(data))]
print(sorted_data)  # 输出: [0, 1, 2, 3, 5, 8, 9]

        可以看到,通过多次弹出堆中的最小元素,实现了对列表的排序。 

1.4 堆的总结

        堆在Python中是一个十分强大的数据结构,具有以下几个优点:

  • 高效的插入和删除操作:堆的插入和删除最小值(或最大值)的操作时间复杂度为O(log n),即使在大规模数据处理中也能保持较高的性能。
  • 快速获取最值:堆的根节点即为最小(或最大)值,可以在O(1)的时间内获取。
  • 灵活的应用场景:堆广泛应用于优先队列、排序算法(如堆排序)以及图算法中(如Dijkstra最短路径算法)等。

        然而,堆也存在一些局限性:

  • 不适合查找和修改操作:由于堆并非按照顺序排列,无法快速地找到指定元素进行修改。
  • 无法保序:堆并不要求所有元素有序,它只保证了最值的有序性。
  • 空间占用较大:堆的实现需要额外的存储空间,其中一些节点可能永远无法被访问到。

        总的来说,堆是一种强大而灵活的数据结构,特别适用于对最值操作频繁的场景。在Python中,内置的heapq模块提供了堆的实现方式,开发者可以利用该模块快速地应用堆数据结构,提高程序的效率和性能。

二、栈

2.1 栈的简介

2.1.1 栈的定义

        栈是一种线性数据结构,其特点是后进先出(Last-In-First-Out,LIFO)。栈有两个主要操作,即压栈(Push)和弹栈(Pop)。压栈将数据放入栈顶,而弹栈则从栈顶移除数据。除此之外,栈还具备返回栈顶元素(Top)的功能。

2.1.2 栈的特性

  1. 栈除了遵循后进先出的原则外,还有以下特性:

  • 栈的容量是固定的。当栈达到其最大容量时,再次压栈操作将导致栈溢出。
  • 栈可以为空,也可以达到最大容量。
  • 栈中的元素不可随机访问。只能通过弹栈获取栈顶元素。

2.1.3 栈的应用场景

        栈的特性使得它在许多领域有着广泛的应用。常见的应用场景包括:

  • 逆序输出:栈可以用于将输入的字符串逆序输出。
  • 表达式计算:栈可以用于处理数学表达式,并解决优先级问题。
  • 函数调用:栈用于存储函数调用过程中的局部变量和返回地址。
  • 浏览器后退:浏览器的“后退”功能通过一个栈来实现。

2.2 栈的发展史

2.2.1 早期栈(Early Stack)

        早期的计算机的存储器是有限的,因此数据结构的设计也受到限制。早期计算机栈的实现方式是使用堆栈指针(Stack Pointer)作为一个寄存器。计算机通过将指令和数据保存在内存上的栈中,实现函数调用和返回地址的管理。

2.2.2 数组栈(Array-Based Stack)

        随着计算机存储器的改进,栈可以使用数组来实现,通过定义一个固定大小的数组来储存栈中的元素。数组栈具有较高的访问速度,但其容量是固定的。

2.2.3 链表栈(Linked List-Based Stack)

        为了克服数组栈容量固定的问题,链表栈(Linked List-Based Stack)提供了一种动态的栈实现方式。链表栈使用链表结构来储存栈中的元素,使得栈的容量可以根据需求动态增加或减少。链表栈通常需要更多的内存空间用于储存指针。

2.2.4 动态数组栈(Dynamic Array-Based Stack)

        动态数组栈是数组栈和链表栈的结合体。它使用数组来储存栈中的元素,但具有动态增长和缩小容量的功能。当栈的大小超过数组容量时,动态数组栈会自动重新分配更大的内存空间。相比链表栈,动态数组栈的访问速度更快,但在扩容时需要额外的内存分配和数据复制操作。

2.3 栈的使用方法

        栈是一种常见的数据结构,它的特点是“后进先出”(Last-In-First-Out,LIFO)。在Python中,我们可以使用列表(List)来实现栈。

2.3.1 初始化栈

        初始化一个空栈,可以使用空列表表示。示例代码如下:

stack = []

2.3.2 压栈(入栈)

        将元素添加到栈的顶部,称为压栈或入栈。可以使用列表的 append() 方法将元素添加到栈的末尾。示例代码如下:

stack.append(1)
stack.append(2)
stack.append(3)

        栈的元素现在变为 [1, 2, 3]。 

2.3.3 弹栈(出栈)

        从栈的顶部移除元素,称为弹栈或出栈。可以使用列表的 pop() 方法将栈顶的元素移除并返回。示例代码如下:

element = stack.pop()
print(element)  # 输出:3

        栈的元素现在变为 [1, 2]。 

2.3.4 获取栈顶元素

        获取栈顶的元素,但并不移除它。可以直接使用列表的索引 -1 来获取栈顶元素。示例代码如下:

top_element = stack[-1]
print(top_element)  # 输出:2

2.3.5 判断栈是否为空 

        通过检查栈的长度是否为零,可以确定栈是否为空。可以使用列表的 len() 方法获取栈的长度。示例代码如下:

python
is_empty = len(stack) == 0
print(is_empty)  # 输出:False

2.3.6 显示栈的元素 

        可以使用循环遍历列表来显示栈的元素。示例代码如下:

for element in stack:
    print(element)
# 输出:
# 1
# 2

2.3.7 综合示例代码如下:

stack = []
stack.append(1)
stack.append(2)
stack.append(3)

element = stack.pop()
print(element)  # 输出:3

top_element = stack[-1]
print(top_element)  # 输出:2

is_empty = len(stack) == 0
print(is_empty)  # 输出:False

for element in stack:
    print(element)
# 输出:
# 1
# 2

        栈在实际应用中有广泛的用途,比如递归函数的调用、表达式求值、深度优先搜索等。掌握栈的使用方法对于Python编程非常重要。

2.4 栈的总结

2.4.1 栈的特点:

        栈是一种受限的线性数据结构,存储元素的顺序按“后进先出”原则。由于栈操作的特殊性,栈具有一些独特的性质:常数时间复杂度的插入和删除,但只能访问栈顶元素。

2.4.2 基本操作:

  • 入栈(push):将元素添加到栈顶。
  • 出栈(pop):删除栈顶元素,并返回其值。
  • 栈顶元素获取(top):返回栈顶元素的值。
  • 栈是否为空(isEmpty):判断栈是否为空。
  • 栈的大小(size):返回栈中元素的个数。

2.4.3 栈的应用:

  • 函数调用:函数的调用顺序使用栈来记录,每当一个函数被调用,其调用信息被压入栈中,当函数执行完毕后再将其弹出。
  • 括号匹配:栈可以用来检查表达式中的括号是否匹配,遇到左括号入栈,遇到右括号与栈顶元素进行匹配。
  • 浏览器的前进后退:浏览器的前进后退功能可以通过两个栈来实现,一个栈用于存储用户的浏览记录,另一个栈用于存储用户的后退记录。

2.4.4 栈的实现:

        在Python中,可以使用列表(list)来实现栈的功能。通过列表的append()方法实现入栈操作,使用pop()方法实现出栈操作。此外,还可以使用collections模块中的deque来实现栈,deque是一个双端队列,可以实现高效的入栈和出栈操作。

        综上所述,栈作为一种受限的线性数据结构,在计算机科学中有着广泛的应用。它的发展始于硬件系统,随着软件系统的发展得到了进一步的拓展。栈不仅仅是数据结构中的一个概念,更是我们在编程中常用的一种工具和思维方式。掌握栈的基本概念和操作,对于理解算法和编程语言的工作方式具有重要意义。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/703444.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

移除所有本地应用程序(数据库)加密设置

大家好,才是真的好。 最近我就有这样一个烦恼,要移除Notes本地的所有本地应用程序(数据库)的加密设置,这样就可以放到Domino服务器上,然后支持其他电脑上不同的Notes访问。毕竟,默认地&#xf…

Open-World Class Discovery with Kernel Networks (ICDM 2020)

Open-World Class Discovery with Kernel Networks (ICDM 2020) 摘要 我们研究了一个开放世界类发现问题,在这个问题中,训练样本是来自旧类有标签的样本,而我们从没有标记的测试样本中发现新的类。解决这一范式有两个关键的挑战:(a)将知识从…

【ESP-IDF】在squareline studio上设计GUI并移植到esp-box上

因为squareline studio软件中适配了ESP-BOX,所以作者本想直接使用该软件创建的工程,但是会出现花屏的现象,也不知道是不是没有做好esp-box-lite的适配。 因此只能先用squareline studio设计好GUI,然后再导出其代码,在其…

实时数仓详解

前言 本文隶属于专栏《大数据理论体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见大数据理论体系 背景 伴随着社会的发展,用户对数据仓库…

ChatGPT中 top_p 和 temperature 的作用机制

1. temperature 的作用机制 GPT 中的 temperature 参数调整模型输出的随机性。随机性大可以理解为多次询问的回答多样性、回答更有创意、回答更有可能没有事实依据。随机性小可以理解为多次询问更有可能遇到重复的回答、回答更接近事实(更接近训练数据)…

pycharm快捷键

目录 1、代码编辑快捷键 2、搜索/替换快捷键 3、代码运行快捷键 4、代码调试快捷键 5、应用搜索快捷键 6、代码重构快捷键 7、动态模块快捷键 8、导航快捷键 9、通用快捷键 🎁更多干货 完整版文档下载方式: 1、代码编辑快捷键 CTRL ALT SP…

Vue-Element-Admin项目学习笔记(9)表单组件封装,父子组件双向通信

前情回顾: vue-element-admin项目学习笔记(1)安装、配置、启动项目 vue-element-admin项目学习笔记(2)main.js 文件分析 vue-element-admin项目学习笔记(3)路由分析一:静态路由 vue-element-adm…

TOWARDS A UNIFIED VIEW OF PARAMETER-EFFICIENT TRANSFER LEARNING

本文也是属于LLM系列的文章,针对《TOWARDS A UNIFIED VIEW OF PARAMETER-EFFICIENT TRANSFER LEARNING》的翻译。 关于参数有效迁移学习的统一观点 摘要1 引言2 前言2.1 Transformer结构综述2.2 之前的参数高效调优方法综述 3 弥合差距-统一的视角3.1 仔细观察Pref…

火山引擎A/B测试推出智能流量调优实验,助力汽车行业破局营销困境

更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 2023年是汽车行业挑战加剧的一年,在这样一个变革时期,多家车企都在进行创新技术和战略调整,实现灵活的科学决策,在发…

03 Web全栈 浏览器内置对象/事件/ajax

浏览器是一个JS的运行时环境,它基于JS解析器的同时,增加了许多环境相关的内容,用一张图表示各个运行环境和JS解析器的关系如下: 我们把常见的,能够用JS这门语言控制的内容称为一个JS的运行环境,常见的运行环…

PDF怎么在线编辑?PDF编辑软件推荐!​

PDF怎么在线编辑?PDF是一种常见的文档格式,用于存储和共享各种类型的文档,如电子书、报告、表格、合同和演示文稿等。然而,PDF文档通常是只读的,无法直接进行编辑。在过去,要编辑PDF文档通常需要购买专业的…

JVM 常量池、即时编译与解析器、逃逸分析

一、常量池 1.1、常量池使用 的数据结构 常量池底层使用HashTable key 是字符串和长度生成的hashValue,然后再hash生成index, 改index就是key;Value是一个HashTableEntry; 1、key hashValue hash string(name, len) i…

高级DBA手把手教你解决clickhouse数据库宕机生产事故实战全网唯一

高级DBA手把手教你解决clickhouse数据库宕机生产事故实战演练 一、事故描述 生产环境clickhouse宕机,重启之后,反复重启,重启几秒钟又死了。甲方客户叫天,大老板火冒三丈,天下大乱。老板电话打过来,要求半…

webrtc源码阅读之examples/peerconnection

阅读webrtc源码,从examples中的peerconnection开始。版本m98。 一、 基本流程 server端只是做了一个http server,来转发client端的消息。也就是起到了信令服务器的作用,本篇文章不在研究,感兴趣的可以学习一下用cpp搭建http serv…

Mysql架构篇--Mysql(M-M) 主从同步

文章目录 前言一、M-M 介绍:二、M-M 搭建:1.Master1:1.1 my.cnf 参数配置:1.2 创建主从同步用户:1.3 开启复制: 2.Master2:2.1 my.cnf 参数配置:2.2 创建主从同步用户:2.…

飞桨携手登临解读软硬一体技术优势,共推AI产业应用落地

众所周知,AI应用落地面临着场景碎片化、开发成本高、算力成本高等诸多难题,这对AI框架与AI芯片都提出了非常高的要求,即既要满足端、边、云多场景的部署需求,还需要支持自动化压缩与高性能推理引擎深度联动。因此充分发挥软硬一体…

通过一个简单的例子理解 Python 中的多线程

关于进程和线程的概念可以看这篇文章: https://blog.csdn.net/ThinkWon/article/details/102021274 什么时候需要多线程编程?简单来说就是一个程序里面有比较耗时间的操作,你希望先让它单独跑着,直接开始进行下一步的操作(Python默…

centos中部署调用matlab程序

环境: Java8 MATLAB2018b centos7 在本机环境上运行成功后的代码打包部署到服务器上运行会报错,需要在服务器上安装MATLAB的运行环境。 首先下载跟本机MATLAB环境一样的mcr文件。 打开网址 http://cn.mathworks.com/products/compiler/mcr/ 下载对…

Python调用百度地图API实现路径规划提取真实距离、时间

1.注册百度地图开放平台账号 网址:百度地图开放平台 | 百度地图API SDK | 地图开发 2.打开控制台,创建应用、获取AK 如下图所示 桥重点、敲重点、瞧重点 在使用python调用API端口时,我们需要申请的为服务端应用类别,别申请错了…

JS实现简单拼图游戏

JS实现简单拼图游戏 点击“打乱”按钮开始游戏&#xff1b;按下鼠标左键拖动一块到另一块上松开鼠标左键互换。游戏资源为一张图片 我这里名称为 2.jpg&#xff0c;将其与下面的网页文件放在同一目录中即可。 网页文件源码如下&#xff1a; <!DOCTYPE html> <html&…