全网最适合入门的面向对象编程教程:45 Python 实现常见数据结构-链表、树、哈希表、图和堆

news/2024/11/16 3:44:59/文章来源:https://www.cnblogs.com/FreakEmbedded/p/18397570

全网最适合入门的面向对象编程教程:45 Python 实现常见数据结构-链表、树、哈希表、图和堆

image

摘要:

数据结构是计算机科学中的一种组织和存储数据的方式,它决定了数据的访问方式和操作效率,数据结构的选择和实现对程序的性能和设计至关重要。本文主要讲述了如何使用 Python 语言和内置库实现常见数据结构。

原文链接:

FreakStudio的博客

往期推荐:

学嵌入式的你,还不会面向对象??!

全网最适合入门的面向对象编程教程:00 面向对象设计方法导论

全网最适合入门的面向对象编程教程:01 面向对象编程的基本概念

全网最适合入门的面向对象编程教程:02 类和对象的 Python 实现-使用 Python 创建类

全网最适合入门的面向对象编程教程:03 类和对象的 Python 实现-为自定义类添加属性

全网最适合入门的面向对象编程教程:04 类和对象的Python实现-为自定义类添加方法

全网最适合入门的面向对象编程教程:05 类和对象的Python实现-PyCharm代码标签

全网最适合入门的面向对象编程教程:06 类和对象的Python实现-自定义类的数据封装

全网最适合入门的面向对象编程教程:07 类和对象的Python实现-类型注解

全网最适合入门的面向对象编程教程:08 类和对象的Python实现-@property装饰器

全网最适合入门的面向对象编程教程:09 类和对象的Python实现-类之间的关系

全网最适合入门的面向对象编程教程:10 类和对象的Python实现-类的继承和里氏替换原则

全网最适合入门的面向对象编程教程:11 类和对象的Python实现-子类调用父类方法

全网最适合入门的面向对象编程教程:12 类和对象的Python实现-Python使用logging模块输出程序运行日志

全网最适合入门的面向对象编程教程:13 类和对象的Python实现-可视化阅读代码神器Sourcetrail的安装使用

全网最适合入门的面向对象编程教程:全网最适合入门的面向对象编程教程:14 类和对象的Python实现-类的静态方法和类方法

全网最适合入门的面向对象编程教程:15 类和对象的 Python 实现-__slots__魔法方法

全网最适合入门的面向对象编程教程:16 类和对象的Python实现-多态、方法重写与开闭原则

全网最适合入门的面向对象编程教程:17 类和对象的Python实现-鸭子类型与“file-like object“

全网最适合入门的面向对象编程教程:18 类和对象的Python实现-多重继承与PyQtGraph串口数据绘制曲线图

全网最适合入门的面向对象编程教程:19 类和对象的 Python 实现-使用 PyCharm 自动生成文件注释和函数注释

全网最适合入门的面向对象编程教程:20 类和对象的Python实现-组合关系的实现与CSV文件保存

全网最适合入门的面向对象编程教程:21 类和对象的Python实现-多文件的组织:模块module和包package

全网最适合入门的面向对象编程教程:22 类和对象的Python实现-异常和语法错误

全网最适合入门的面向对象编程教程:23 类和对象的Python实现-抛出异常

全网最适合入门的面向对象编程教程:24 类和对象的Python实现-异常的捕获与处理

全网最适合入门的面向对象编程教程:25 类和对象的Python实现-Python判断输入数据类型

全网最适合入门的面向对象编程教程:26 类和对象的Python实现-上下文管理器和with语句

全网最适合入门的面向对象编程教程:27 类和对象的Python实现-Python中异常层级与自定义异常类的实现

全网最适合入门的面向对象编程教程:28 类和对象的Python实现-Python编程原则、哲学和规范大汇总

全网最适合入门的面向对象编程教程:29 类和对象的Python实现-断言与防御性编程和help函数的使用

全网最适合入门的面向对象编程教程:30 Python的内置数据类型-object根类

全网最适合入门的面向对象编程教程:31 Python的内置数据类型-对象Object和类型Type

全网最适合入门的面向对象编程教程:32 Python的内置数据类型-类Class和实例Instance

全网最适合入门的面向对象编程教程:33 Python的内置数据类型-对象Object和类型Type的关系

全网最适合入门的面向对象编程教程:34 Python的内置数据类型-Python常用复合数据类型:元组和命名元组

全网最适合入门的面向对象编程教程:35 Python的内置数据类型-文档字符串和__doc__属性

全网最适合入门的面向对象编程教程:36 Python的内置数据类型-字典

全网最适合入门的面向对象编程教程:37 Python常用复合数据类型-列表和列表推导式

全网最适合入门的面向对象编程教程:38 Python常用复合数据类型-使用列表实现堆栈、队列和双端队列

全网最适合入门的面向对象编程教程:39 Python常用复合数据类型-集合

全网最适合入门的面向对象编程教程:40 Python常用复合数据类型-枚举和enum模块的使用

全网最适合入门的面向对象编程教程:41 Python常用复合数据类型-队列(FIFO、LIFO、优先级队列、双端队列和环形队列)

全网最适合入门的面向对象编程教程:42 Python常用复合数据类型-collections容器数据类型

全网最适合入门的面向对象编程教程:43 Python常用复合数据类型-扩展内置数据类型

全网最适合入门的面向对象编程教程:44 Python内置函数与魔法方法-重写内置类型的魔法方法

更多精彩内容可看:

给你的 Python 加加速:一文速通 Python 并行计算

一文搞懂 CM3 单片机调试原理

肝了半个月,嵌入式技术栈大汇总出炉

电子计算机类比赛的“武林秘籍”

一个MicroPython的开源项目集锦:awesome-micropython,包含各个方面的Micropython工具库

Avnet ZUBoard 1CG开发板—深度学习新选择

SenseCraft 部署模型到Grove Vision AI V2图像处理模块

文档和代码获取:

可访问如下链接进行对文档下载:

https://github.com/leezisheng/Doc

image

本文档主要介绍如何使用 Python 进行面向对象编程,需要读者对 Python 语法和单片机开发具有基本了解。相比其他讲解 Python 面向对象编程的博客或书籍而言,本文档更加详细、侧重于嵌入式上位机应用,以上位机和下位机的常见串口数据收发、数据处理、动态图绘制等为应用实例,同时使用 Sourcetrail 代码软件对代码进行可视化阅读便于读者理解。

相关示例代码获取链接如下:https://github.com/leezisheng/Python-OOP-Demo

正文

数据结构基本知识

实际上,前文讲到的队列、列表、集合、字典等均属于数据结构的一部分。数据结构,作为一种代码结构,其核心目的在于有序地存储与组织数据,进而简化信息的修改、导航与访问过程。它不仅决定了数据的收集方式、实现的功能以及数据间的相互关系,更在计算机科学和编程的各个领域,如操作系统、前端开发以及机器学习等,发挥着不可或缺的作用。数据结构是解决问题的高效且真实的关键构件。每一种数据结构都有其独特的适用场景和任务。

数据结构可划分为逻辑结构与物理结构两大类:

  1. 逻辑结构:是指数据元素间逻辑关系的数据组织方式,这种关系侧重于元素间的相对位置,而与数据在计算机中的实际存储位置无关。

在逻辑结构的分类中,可以分为线性结构和非线性结构:

  1. 物理结构:又称存储结构,描述的是数据逻辑结构在计算机存储空间中的具体实现形式。数据的逻辑结构通常可以映射为多种物理结构。物理结构是实现数据元素间逻辑关系的具体手段。一种逻辑结构可以根据实际需求转化为多种物理结构。常见的物理结构有:
    • ① 顺序存储,其特点是元素在内存中的存储顺序是连续的,线性表的元素通过一组连续的存储单元来存储。
    • ② 链式存储,在这种方式中,内存中的存储元素不必连续,每个元素节点包含数据元素和指向相邻元素的指针信息。
    • ③ 索引存储,除了存储节点信息,还通过附加的索引表来标识节点的内存地址,索引表由多个索引项构成。
    • ④ 散列存储,又称 Hash 存储,其中节点的存储地址由节点的关键码值直接决定。

接下来,我们将简要介绍如何利用面向对象编程的思维和 Python 内置数据类型去实现其他的数据结构,注意该部分并非本书重点内容,所以这里只是浅显的讲一下数据结构,其中实现代码主要是帮助读者理解而非实际应用。

Python 实现链表

链表是一种物理存储单元上非连续、非顺序的存储结构,是由许多相同数据类型的数据项按照特定顺序排列而成的线性表。链表有一系列节点组成,所谓节点就是指链表中的每一个元素,每个节点包含两个数据,一个是存储元素的数据域(值),另一个是存储下一个节点地址的指针域。

image

链表中的第一个节点称为头节点,最后一个节点称为尾节点,其中尾节点的 next 指向为 null。链表可以是单链,也可以是双链,这取决于每个节点是只有一个指向下一个节点的指针,还是还有一个指向前一个节点的指针。你可以把链表想象成一条链;单个链接只与相邻的链接有一个连接,但所有链接一起形成一个更大的结构。

class Node:def __init__(self, dataval=None):self.dataval = datavalself.nextval = None
class SLinkedList:def __init__(self):self.headval = None
list1 = SLinkedList()
list1.headval = Node("Mon")
e2 = Node("Tue")
e3 = Node("Wed")
_# Link first Node to second node_
list1.headval.nextval = e2
_# Link second Node to third node_
e2.nextval = e3

链表具有以下优势:新元素插入和删除更高效、比数组更易于重组、高级数据结构 (如图形或树)都是基于链表的,缺点是:每个数据点的指针存储增加了内存使用量同时必须始终从头节点遍历链表以查找特定元素。

Python 实现树

树是另一种基于关系的数据结构,专门用于表示层次结构。与链表一样,它们也被 Node 对象填充,Node 对象包含一个数据值和一个或多个指针,用于定义其与直接节点的关系。每棵树都有一个根节点,所有其他节点都从根节点分支出来。根节点包含指向它正下方所有元素的指针,这些元素被称为它的子节点。这些子节点可以有它们自己的子节点。在同一层上的任何节点都称为同级节点。没有连接子节点的节点称为叶节点。

image

我们平时用到最多的就是二叉树,二叉树最常见的应用是二叉搜索树。二叉搜索树擅长于搜索大量的数据集合,因为时间复杂度取决于树的深度而不是节点的数量。二叉树具有以下特点:

  • 左子树只包含元素小于根的节点。
  • 右子树只包含元素大于根的节点。
  • 左右子树也必须是二叉搜索树。他们必须以树的“根”来遵循上述规则。
  • 不能有重复的节点,即不能有两个节点具有相同的值。
lass Node:def __init__(self, data):self.left = Noneself.right = Noneself.data = datadef insert(self, data):
_# Compare the new value with the parent node_if self.data:if data < self.data:if self.left is None:self.left = Node(data)else:self.left.insert(data)elif data > self.data:if self.right is None:self.right = Node(data)else:self.right.insert(data)else:self.data = data
_# Print the tree_def PrintTree(self):if self.left:self.left.PrintTree()print( self.data),if self.right:self.right.PrintTree()
_# Use the insert method to add nodes_
root = Node(12)
root.insert(6)
root.insert(14)
root.insert(3)
root.PrintTree()

树形结构的搜索效率高非常适合存储分层数据(如文件位置等),但仅仅适用于排序的列表,未排序的数据退化为线性搜索。

Python 实现哈希表

哈希表又叫散列表,哈希表是一种复杂的数据结构,能够存储大量信息并有效检索特定元素。此结构存储的是由键(key)和值(value)组成的数据,根据键直接访问存储在内存存储位置的数据结构。

image

每个输入键都要经过一个哈希函数,该函数将其从初始形式转换为一个整数值,称为哈希。哈希函数必须始终从相同的输入产生相同的哈希,必须快速计算,并产生固定长度的值。Python 包含一个内置的 hash()函数,可以加速实现。然后,该表使用散列来查找所需值(称为存储桶)的一般位置。然后,程序只需要在这个子组中搜索所需的值,而不必搜索整个数据池。除了这个通用框架之外,根据应用程序的不同,哈希表也可能非常不同。有些可能允许来自不同数据类型的键,而有些可能有不同的设置桶或不同的散列函数。

下面是一个 Python 代码中的哈希表示例:

import pprint
class Hashtable:def __init__(self, elements):self.bucket_size = len(elements)self.buckets = [[] for i in range(self.bucket_size)]self._assign_buckets(elements)def _assign_buckets(self, elements):for key, value in elements: _#calculates the hash of each key_hashed_value = hash(key)index = hashed_value % self.bucket_size _# positions the element in the bucket using hash_self.buckets[index].append((key, value)) _#adds a tuple in the bucket_def get_value(self, input_key):hashed_value = hash(input_key)index = hashed_value % self.bucket_sizebucket = self.buckets[index]for key, value in bucket:if key == input_key:return(value)return Nonedef __str__(self):return pprint.pformat(self.buckets) _# pformat returns a printable representation of the object_
if __name__ == "__main__":capitals = [('France', 'Paris'),('United States', 'Washington D.C.'),('Italy', 'Rome'),('Canada', 'Ottawa')]
hashtable = Hashtable(capitals)
print(hashtable)
print(f"The capital of Italy is {hashtable.get_value('Italy')}"

哈希表可以将任何形式的键隐藏为整数索引,对于大型数据集搜索非常有效,常常应用于用于频繁查询的大型数据库或根据关键字检索的系统。

Python 实现图

图是一种数据结构,用于表示数据顶点(图的节点)之间关系的可视化。将顶点连接在一起的链接称为边。边定义了哪些顶点被连接,但没有指明它们之间的流向。每个顶点与其他顶点都有连接,这些连接以逗号分隔的列表形式保存在顶点上。还有一种特殊的图叫做有向图,它定义了关系的方向,类似于链表。在建模单向关系或类似流程图的结构时,有向图很有帮助。

在 Python 中,图的最佳实现方式是使用字典,每个顶点的名称作为键,边列表作为值。

_# Create the dictionary with graph elements_
graph = { "a" : ["b","c"],"b" : ["a", "d"],"c" : ["a", "d"],"d" : ["e"],"e" : ["d"]}
_# Print the graph          _
print(graph)

图在存储数据上有着比较复杂和高效的算法,分别有邻接矩阵 、邻接表、十字链表、邻接多重表、边集数组等存储结构。常见的图遍历算法就是广度优先算法和深度优先算法。它适用于网络或类似网络的结构建模,可以通过代码快速传达视觉信息,但是在大型图中很难理解顶点链接同时从图表中解析数据的时间昂贵。

Python 实现堆

堆比较特殊,是一种图的树形结构。被用于实现“优先队列”(priority queues),优先队列是一种数据结构,可以自由添加数据,但取出数据时要从最小值开始按顺 序取出。在堆的树形结构中,各个顶点被称为“结点”(node),数据就存储在这些结点中。只要满足下面两个特点的树形结构就是堆:

  • 堆是一个完全二叉树(所谓完全二叉树就是除了最后一层其他层的节点个数都是满的)。
  • 堆中每一个节点的值都必须大于等于或者小于其子树中每一个节点的值。

image

我们可以使用 heapq 模块实现一个适合与 Python 的列表一起使用的最小堆:

import heapq
from heapq_showtree import show_tree
from heapq_heapdata import dataheap = []
print('random :', data)
print()for n in data:print('add {:>3}:'.format(n))heapq.heappush(heap, n)show_tree(heap)

里面有两个函数需要注意:

  • heapq.heappush(heap, item):将值 item 推送到 heap,保持堆不变。
  • heapq_showtree.show_tree(heap):用于展示树形结构。

image

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unicode编码介绍

什么是Unicode编码? Unicode是字符编码规范,它定义了所有文字的编码规则。说通俗点就是它按照某个规则给每个字符都分配了一个数字编号(比如:A的编号为65或0x0041,万的编号为19981或0x4e0d),相当于是一个编号库。这个数字编号也叫Unicode码。最开始这个编号使用2个字节表…

LeetCode题集-2 - 两数相加

递归法和迭代法有什么差别,通过两数相加算法来搞明白,一举多得这个题目是什么意思呢?简单来说就是把两个链表平铺开,头节点对齐,然后从头开始相同的节点相加,满10则进位,进位值与下个节点继续相加,当一个链表没有节点时候则可以把没有节点当做0继续与有节点的链表继续相…

pytesseract实现识别pdf文件并将内容写入word文档中

步骤一:先安装tesseract-ocr-w64-setup-5.4.0.20240606 (安装记得语言包只安装需要的即可) 步骤二:将安装目录添加到系统环境变量中 (网上很多这一步之后就说可以运行程序了其实不然,一直报错没有添加到环境变量中) 步骤三:第四步:可以正常运行啦 =================…

消息中间件ms

消息中间件rabbitmq如何保证数据不丢失 MQ高级搜消息可靠性 常用于mq重复消费问题解决 搜消费者重复消息问题延迟队列有了解过吗?(私信交换机) 搜延迟消息如果有100w的消息堆积到mq怎么办(消息堆积)高可用机制了解过吗

9种最高频的架构模式

这9种最高频的架构模式了解一下,什么样的业务适合事件驱动,什么样的业务适合ETL,什么类型的服务依赖streaming,分别有什么样的特征最好事前准备,我的专栏会分析每种架构的方法论和面试注意事项,感兴趣的可以关注

gadget驱动框架(一)

之前在linux移植udc驱动的时候,没有深入的理解整个gadget驱动框架,现在重新再屡屡gadget驱动,以便后期再次学习。本系列的文章以虚拟串口进行分析,相关源码均是基于linux4.19.123。 gadget驱动框架 gadget源码主要在:drivers/usb/gadget,以虚拟串口为例,对源文件做简单说…

Transfusion: Predict the Next Token and Diffuse Images with One Multi-Modal Model(2024,8)

Transfusion: Predict the Next Token and Diffuse Images with One Multi-Modal Model(2024,8) Paper TODO: 目前没有开源代码,实时关注一下official code,Meta的工作基本开源的.本文给出了一种新的T2I的方法. lucidrains的代码本质是将LLM的transformer和图像中的diffusion结…

代码整洁之道--读书笔记(1)

代码整洁之道简介: 本书是编程大师“Bob 大叔”40余年编程生涯的心得体会的总结,讲解要成为真正专业的程序员需要具备什么样的态度,需要遵循什么样的原则,需要采取什么样的行动。作者以自己以及身边的同事走过的弯路、犯过的错误为例,意在为后来者引路,助其职业生涯迈上更…

Towards Robust Blind Face Restoration with Codebook Lookup Transformer(NeurIPS 2022) | Codeformer

Towards Robust Blind Face Restoration with Codebook Lookup Transformer(NeurIPS 2022) 这篇论文试图解决的是盲目面部恢复(blind face restoration)问题,这是一个高度不确定的任务,通常需要辅助指导来改善从低质量(LQ)输入到高质量(HQ)输出的映射,或者补充输入中丢…

[MySQL]B+树能存储多少数据

MySQL中一个B+树能存储多少数据MySQL中InnoDB页的大小默认是16k。也可以自己进行设置。(计算机在存储数据的时候,最小存储单元是扇区,一个扇区的大小是 512 字节,而文件系统(例如 XFS/EXT4)最小单元是块,一个块的大小是 4KB。 InnoDB 引擎存储数据的时候,是以页为单位的…

基于 GoFrame 框架的 Go 项目打包成镜像,并上传至 Harbor 镜像库

本文通过将一个简单的 gf 项目推送到 harbor,简单介绍了整个流程和过程中用到的命令。〇、前言 在云服务时代最流行的部署方式就是容器部署,这也是最推荐的部署方式。 对于 GoFrame 框架就不多介绍了,直接来初始化一个 demo,备用。 // 初始化一个项目:gf-demo gf init gf-…

ChatOn安卓版(智能AI聊天机器人) v1.48.435-476 高级版

概述 ChatOn 构建于ChatGPT和GPT-4o之上,为用户提供市场上最优秀的中文AI聊天机器人。AI聊天机器人能够达到一个全新水平的仿人类互动:当你为某一场正式会议准备演讲,苦思动人的措辞,或寻求写作方面的帮助时,这款智能机器人和AI助手都会统统帮你搞定。 软件功能 1、AI 写…