python自学之《21天学通Python》(15)——第18章 数据结构基础

news2025/1/16 6:40:38

数据结构是用来描述一种或多种数据元素之间的特定关系,算法是程序设计中对数据操作的描述,数据结构和算法组成了程序。对于简单的任务,只要使用编程语言提供的基本数据类型就足够了。而对于较复杂的任务,就需要使用比基本的数据类型构造更加复杂的数据结构了。

18.1 表、栈和队列

表、栈和队列都是基本的线性数据结构。由于Python设计良好的数据结构,其列表就可以当作表来使用,而且列表的某些特性跟链表都相似,因此在Python中表的实现非常简单。对于栈和队列,则可以自己编写程序来构建。

18.1.1 用列表来创建表

表是最基本的数据结构,在Python中可以使用列表来创建表。而在C语言中,一般使用数组来创建表。由于使用数组创建表,对表中元素进行插入和删除操作的开销较大。当插入一个元素时,要先将该元素后的所有元素,从最后一个元素开始,依次向后移动一个位置。完成元素移动后,再将元素插入到数组中。同样,要删除表中的元素时,首先删除元素,然后将位于该元素之后的元素从前向后,依次向前移动一个位置。

如果一个表含有的元素较多,而要进行插入或删除的位置又比较靠近表的前端,则移动表中元素的操作将耗费大量的时间。为了减少插入和删除元素的线性开销,于是就出现了使用链表代替表。在C语言中,链表中不仅保存数据,还保存了指向下一个元素的指针,如图18.1所示。当进行插入操作时,要先将位于插入元素前的元素的指针赋值给插入元素。完成赋值后再将插入元素的地址赋值给位于其前的元素,如图18.2所示。当进行删除元素时,只需将要删除元素的指针赋值给其前边的元素即可,如图18.3所示。

在这里插入图片描述

使用链表,可以降低插入删除、元素的线性开销。然而,由于链表中不仅存储了数据,而且还保存了指向下一个元素的指针,因而使用链表将占用更大的存储空间。而在Python中,列表本身就提供了插入和删除操作。因此,在Python中列表也可以充当链表使用,而不用自己另外编写程序来构建。

还有一种链表,称之为双向链表,如图18.4所示。双向链表中不仅保存了指向下一元素地址的指针,而且还保存了指向其上一个元素地址的指针。相对于单向链表,双向链表需要占用更多的存储空间,但使用双向列表可以完成正序和倒序扫描链表。

在这里插入图片描述

18.1.2 自定义栈数据结构

栈可以看作在同一位置上进行插入和删除的表,这个位置一般就称为栈顶。栈的基本操作是进栈和出栈,栈可以看作是一个容器,如图18.5所示。先入栈的数据保存在容器底部,后入栈的数据保存在容器顶部。在出栈的时候,后入栈的数据先出,而先入栈的数据则后出,因此栈有一个特性叫做后进先出(LIFO)。

在这里插入图片描述
在Python中,仍然可以使用列表来存储堆栈数据。通过创建一个堆栈类,实现对堆栈进行操作的方法。例如,进栈PUSH方法、出栈POP方法,编写检查栈是否为满栈,或者是否为空栈的方法等。

【实例18-1】 演示了在Python中创建了一个简单的堆栈结构,代码如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
【代码说明】代码中共定义了一个堆栈类PyStack和一个堆栈异常类StackException,堆栈类有一个初始化参数,即堆栈大小,在堆栈类中定义了关于堆栈操作的相关方法。

【运行效果】运行pystack.py程序后,将输出如下内容:

在这里插入图片描述

18.1.3 实现队列功能

队列与栈的结构类似,如图18.5所示。但不同的是队列的出队操作是在队首元素进行的删除操作。因而对于队列而言,先入队的元素将先出队。因此队列的特性可以称之为先进先出(FIFO)。

在这里插入图片描述
和堆栈类似,在Python中同样可以使用列表来构建一个队列,并完成对队列的操作。

【实例18-2】 演示了一个创建简单的队列的实例,代码如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
【代码说明】该实例中的代码与实例18-1也是相似的,定义了队列类及其相关的操作方法,以及一个异常类。

【运行效果】运行pyqueue.py程序后输出如下:

在这里插入图片描述
在这里插入图片描述

18.2 树和图

树和前边所讲的表、栈和队列等这些线性数据结构不同,树不是线性的。在处理较多数据时,使用线性结构较慢,而使用树结构则可以提高处理速度。不过,相对于线性的表、栈和队列等线性数据结构来说,树的构建便显得较为复杂了。

18.2.1 用列表构建树

树是一种非线性的数据结构,如图18.7所示。之所以称之为树,是因为其形状像一颗倒置的树。每棵树都有一个根节点,如图18.7所示的树中,Root为根节点;A、B、C为Root的儿子,Root为A、B、C的父亲,A、B、C为兄弟;同样,A为D、E的父亲,D、E为A的儿子,D、E为兄弟;D、E为Root的孙子,Root为D、E的祖父。在树中,如果一个元素没有儿子,则称之为树的叶子。

在这里插入图片描述

在Python中,树的实现可以使用列表或者类的方式。使用列表的方式较为简便,但树的构建过程较为复杂。使用类的方式构建树时,需要首先确定树中的节点所能拥有的最大儿子数。因为每个节点所拥有的儿子数量并不一定相同,因此使用类的方法将占用更大的存储空间。

【实例18-3】 演示了以列表的形式构建了如图18.7所示的树,代码如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

18.2.2 实现二叉树类与遍历二叉树

二叉树是一类比较特殊的树,在二叉树中每个节点最多只有两个儿子,分为左和右,如图18.8所示。相对于树而言,二叉树的构建和使用都要简单得多。

在这里插入图片描述
任何一棵树,都可以通过变换转换成一棵二叉树。
在Python中,二叉树的构建和树一样,可以使用列表或者类的方式。由于二叉树中的节点具有确定的儿子数,因此,使用类的方式要更为简便。

【实例18-4】 演示了用比较简单的方式生成了如图18.8所示的树,代码如下:

在这里插入图片描述
在这里插入图片描述
【代码说明】代码中首先定义了一个表示节点的类BTree,在该类构造方法中,建立了三个实例变量,分别用来保存其节点值、左子节点和右子节点,然后通过实例化根点,不断从根开始构造该二叉树。

当创建好一棵二叉树后,可以按照一定的顺序对树中所有的元素进行遍历。按照先左后右,树的遍历方法有三种:先序遍历、中序遍历和后序遍历。

先序遍历的次序是:如果二叉树不为空,则访问根节点,然后访问左子树,最后访问右子树;否则,程序退出。

中序遍历的次序是:如果二叉树不为空,则先访问左子树,然后访问根节点,最后访问右子树;否则,程序退出。

后序遍历的次序是:如果二叉树不为空,则先访问左子树,然后访问右子树,最后访问根节点。

【实例18-5】 演示了使用三种遍历方式遍历如图18.8所示的树,代码如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
【代码说明】代码中定义了与实例18-4相同的类,之后分别定义了先序遍历、中序遍历、后序遍历的函数,在遍历函数中采用了递归调用的方式来完成功能。

【运行效果】演示了使用三种遍历方式遍历如图18.8所示的树,其遍历结果如下:

运行TreeTraversal.py程序后输出如下。

在这里插入图片描述
在这里插入图片描述

18.2.3 用字典构建与搜索图

图也是非线性的数据结构,图是由顶点和边组成的。如果图中的顶点是有序的,那么图是有方向的,称之为有向图,如图18.9所示;否则,图是无方向的,称之为无向图。在图中,由顶点组成的序列称之为路径。

在这里插入图片描述
图和树相比,少了树明显的层次结构。在Python中,可以采用字典的方式来创建图,图中的每个元素是字典中的键,该元素所指向的是图中其他元素组成键的值。

同树一样,对于图来说,也可以对其进行遍历。除了遍历以外,可以在图中搜索所有的从一个顶点到另一个顶点的路径。图中的每一顶点可以看作为一个城市,路径可以看作是城市到城市之间的公路。因此,通过搜索所有的路径,可以找到一个顶点到另一个顶点的最短路径,即城市到城市间的最短路线。

【实例18-6】 演示了使用字典的方式构建了如图18.9所示的有向图,并搜索图中的路径,代码如下:

在这里插入图片描述
在这里插入图片描述
【代码说明】代码中采用字典来构造图,并定义了搜索图的函数generatePath(),并且其中也使用了递归调用。
【运行效果】运行本例代码,将输出如下的内容。

在这里插入图片描述
在这里插入图片描述

18.3 查找与排序

查找和排序是最基本的算法,在很多程序中都会用到查找和排序。其实,在前边各章的例子中己多次使用到Python的函数查找字符串中的子字符串。尽管Python提供的用于查找和排序的函数能够满足绝大多数需求,但还是有必要了解最基本的查找和排序算法,以便在有特殊需求的情况下,可以编写自己的查找、排序程序。

18.3.1 实现二分查找

基本的查找方法有顺序查找、二分查找和分块查找等。其中,顺序查找是最简单的查找方法,就是按数据排列的顺序依次查找,直到找到所查找的数据为止(可查看数据表都未找到的数据)。

二分查找是首先对要进行查找的数据进行排序,有按大小顺序排好的9个数字,如图18.10所示。如果要查找数字5,首先与中间值10进行比较,5小于10,于是对序列的前半部分1~9进行查找。此时,中间值为5,恰好为要找的数字,查找结束。

在这里插入图片描述

分块查找,是介于顺序查找和二分查找之间的一种查找方法。使用分块查找时,首先对查找表建立一个索引表,再进行分块查找。建立索引表时,首先对查找表进行分块,要求“分块有序”,即块内关键字不一定有序,但分块之间有大小顺序。索引表是抽取各块中的最大关键字及其起始位置构成的,如图18.11所示。

在这里插入图片描述
分块查找分两步进行,首先查找索引表,因为索引表是有序的,查找索引表时可以使用二分查找法进行。查找完索引表以后,就确定了要查找的数据所在的分块,然后在该分块中再进行顺序查找。

【实例18-7】 演示了对一个有序列表使用二分查找实例,其代码如下:

在这里插入图片描述
在这里插入图片描述
【代码说明】代码很简单,仅定义了一个用于二分查找的函数BinarySearch(),然后在主程序中调用它进行测试和查找。

在这里插入图片描述

18.3.2 用二叉树排序

相对于查找来说,排序要复杂得多,排序的方法也较多,常用的排序方法有冒泡法排序、希尔排序、二叉树排序和快速排序等。其中二叉树排序是比较有意思的一种排序方法,而且也便于操作。二叉树排序的过程主要是二叉树的建立和遍历的过程。例如有一组数据“3,5,7,20,43,2,15,30”,则二叉树的建立过程如下。

(1)首先将第一个数据3放入根节点;
(2)将数据5与根节点中的数据3比较,由于5大于3,则将5放入3的右子树中;
(3)将数据7与根节点中的数据3比较,由于7大于3,则应将7放入3的右子树中,由于3已经有右儿子5,则将7与5进行比较,因为7大于5,应将7放入5的右子树中;
(4)将数据20与根节点3进行比较,由于20大于3,则应将7放入3的右子树,重复比较,最终将20放到7的右子树中;
(5)将数据43与树中的节点值进行比较,最终将其放入20的右子树中;
(6)将数据2与根节点3进行比较,由于2小于3,则应将2放入3的左子树;
(7)同样的对数据15和30进行处理,最终形成如图18.12所示的树。

在这里插入图片描述
当树创建好后,对树进行中序遍历,得到的遍历结果就是对数据从小到大的排序。如果要从大到小进行排序,则可以先从右子树开始进行中序遍历。

【实例18-8】 演示了一个采用二叉树排序的方式对数据进行排序的实例,其代码如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
【运行效果】运行该示例程序后,输出如下的排序结果:

在这里插入图片描述
在这里插入图片描述

18.4 小结

本章介绍了Python在处理基本数据结构方法的程序编写方法。由于Python设计良好的数据结构,通过列表就可以方便地完成表、栈、队列、树、图等数据结构的操作,因此,掌握了Python列表数据类型的使用,编写操作数据结构中的表、栈、队列、树、图的程序就比较简单了。最后,本章还介绍了用Python编写查找与排序的程序。

18.5 本章习题

在这里插入图片描述

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

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

相关文章

华三OSPF 综合实验

OSPF 实验 实验拓扑 实验需求 按照图示配置 IP 地址按照图示分区域配置 OSPF ,实现全网互通为了路由结构稳定,要求路由器使用环回口作为 Router-id,ABR 的环回口宣告进骨干区域 实验解法 1.配置 IP 地址部分 2.按照图示分区域配置 OS…

FFmpeg从入门到入魔(1):初探FFmpeg框架

1. FFmpeg介绍与裁剪1.1 FFmpeg简介FFmpeg(Fast forword mpeg,音视频转换器)是一个开源免费跨平台的视频和音频流方案,它提供了录制/音视频编解码、转换以及流化音视频的完整解决方案。ffmpeg4.0.2源码目录结构如下:目…

为什么IBDP的文凭更受美国大学的青睐?

家长们可以看到,不管是AP还是A-LEVEL这样的课程,都只是单科的课程(A-LEVEL也是英国发展出来,AP是针对美国大学设计的),学生是可以针对他们的强项去做选修,比如我的化学很强,那我可以…

第十节 集合

集合 什么是集合 集合就是能储存一批元素的容器。 特征: 集合类型可以不固定,大小也是可变的。 ArrayList集合 ArrayList是集合中的一种,它支持索引。 ArrayList集合的对象获取 public ArrayList()创建一个空的集合对象 ArrayList集合的添加…

Hive 一文读懂

Hive 简介1.1 什么是Hive1)hive简介Hive:由Facebook开源用于解决海量结构化日志的数据统计。Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类SQL查询功能。2)Hive本质:将…

Goframe快速创建项目,并使用Cli工具创建dao、service、logic

GoFrame项目创建与Cli工具创建1.项目创建2.Mysql数据库配置3.Cli工具dao自动生成4.业务模型须知5.Cli工具service/logic自动生成 - 接口6.Controller/Api创建1.项目创建 官网 - 项目创建-init 开发文档 - 目录介绍 官网 - 示例项目 1.gf init 项目名 (创建项目…

无法定位程序输入点kernel32.dll,如何修复kernel32.dll

kernel32.dll是Windows操作系统中非常重要的一个系统文件,如果它丢失或损坏可能会导致许多应用程序无法正常运行。今天小编就来给大家详细的讲解一下无法定位程序输入点kernel32.dll,我们要怎么修复这个kernel32.dll缺失的问题。 一.kernel32.dll时候什么…

前端开发环境配置,浏览器跨域配置,代码提交配置git等

这是我目前公司的开发配置文档大家可以参考: 前端文档 1 搭建前端环境 1.1 安装nodejs 1.1.1 nodejs下载地址 https://nodejs.org/dist/v10.15.3/node-v10.15.3-x64.msi(win64) https://nodejs.org/dist/v10.15.3/node-v10.15.3.pkg&…

查询性能较 Trino/Presto 3-10 倍提升!Apache Doris 极速数据湖分析深度解读

从上世纪 90 年代初 Bill Inmon 在《building the Data Warehouse》一书中正式提出数据仓库这一概念,至今已有超过三十年的时间。在最初的概念里,数据仓库被定义为「一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合,用于支持管理…

Python排序 -- 内附蓝桥题:错误票据,奖学金

排序 ~~不定时更新🎃,上次更新:2023/02/28 🗡常用函数(方法) 1. list.sort() --> sort 是 list 的方法,会直接修改 list 举个栗子🌰 li [2,3,1,5,4] li.sort() print(li) …

New Bing怼人、说谎、PUA,ChatGPT已经开始胡言乱语了

最近,来自大洋彼岸那头的ChatGPT科技浪潮席卷而来,微软将chatGPT整合搜索引擎Bing开启内测后,数百万用户蜂拥而至,都想试试这个「百事通」。 赶鸭子上架,“翻车”了? 但短短上线十几天,嵌入了…

5个开源的Java项目快速开发脚手架

概览 : GunspigRuoYiJeecg-bootiBase4J 一、Guns 推荐指数 :⭐⭐⭐⭐⭐ 简介 采用主流框架 : 基于 Spring Boot2.0版本开发,并且支持 Spring Cloud Alibaba 微服务。功能齐全 :包含系统管理,代码生成&a…

python线程池【ThreadPoolExecutor()】批量获取博客园标题数据

转载:蚂蚁学python 网址:【【2021最新版】Python 并发编程实战,用多线程、多进程、多协程加速程序运行】 https://www.bilibili.com/video/BV1bK411A7tV/?p8&share_sourcecopy_web&vd_sourced0ef3d08fdeef1740bab49cdb3e96467实战案…

SpringMVC 面试题

1、什么是SpringMVC? SpringMVC是一个基于Java的实现了MVC设计模式的“请求驱动型”的轻量级WEB框架,通过把model,view,controller 分离,将web层进行职责的解耦,把复杂的web应用分成逻辑清晰的几个部分&am…

Arduino-PWM调光

PWM调光实验什么是PWM?PWM是(Pulse Width Modulation)的简称,中文我们说这是脉冲宽度调制。脉冲宽度调制是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通…

react 函数式组件的hooks

目录 useState useEffect useCallback useMemo useRef useContext useReducer 自定义hooks useState 函数式组件的状态 ,格式: const [value,setValue] useState( {xxxx} ) console.log([value, setValue])打印一下可以看到: value…

腾讯安全与锐捷网络战略合作,威胁情报能力“被集成”

2月28日,腾讯安全和锐捷网络在北京联合举办“威胁情报”战略合作发布会。双方发布了一款集成了腾讯安全威胁情报的新一代防火墙,并举办战略合作签约仪式。会上,锐捷网络安全产品事业部总经理项小升、腾讯安全总经理陈龙代表双方签署战略合作协…

taobao.user.avatar.get

¥开放平台基础API不需用户授权 根据混淆nick查询用户头像 公共参数 请求地址: HTTP地址 http://gw.api.taobao.com/router/rest 公共请求参数: 公共响应参数: 点击获取key和secret 请求参数 请求示例 TaobaoClient client new DefaultTaobaoClient(url, appkey,…

MyBatis中#{}和${}的区别

目录 前言 1、处理参数的方式不同 2、${}的优点 3、SQL注入问题 4、like查询问题 前言 #{}和${}都可以在MyBatis中用来动态地接收参数,但二者在本质上还是有很大的区别。 1、处理参数的方式不同 ${} :预编译处理 MyBatis在处理#{}时&#xff0c…

【Android】全局加载框的使用

项目需求 在网络加载中使用网络加载框,在请求数据或者其他耗时操作的时候,显示加载框,当数据返回之后或者操作完成的时候加载框取消。 效果如下: 需求实现 使用一个开源库【Gloading】实现 项目地址链接: Gloading 1.引入依赖…