dom4j实现为list添加父节点_Heap 堆的实现

堆(数据结构)

什么是堆

堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象

堆的性质

这种用数组实现的二叉树,假设节点的索引值为index,那么:

节点的左孩子节点是 2*index+1,

节点的右孩子节点是 2*index+2,

左孩子节点的父节点是 (index-1) / 2。

右孩子结点的父结点是 (index-2) / 2

最大堆中,父结点的值比每一个子节点的值都要大

最小堆中,父结点的值比每一个子节点的值都要小

堆的插入,取值

堆是一种数据结构,分为最小堆和最大堆,可以用二叉树来表示。

在二叉树的任意的一个三角结构中(一个父节点,两个子节点),需要满足以下两个条件:

1、父节点要是最小的,就是最小堆(或最大的,就是最大堆),两个子节点之间没有要求

2、数据插入的顺序是一层一层的,只有上一层存满,才会有下一层

一、插入(insert)

假设我们有一个原始的最小堆如下:

d5ef70bfbc8dc7724434b53a5c5692e4.png

插入操作:

当插入一个新值时,首先将值放到树的最后的位置,如下图所示。

然后将这个值与父级元素比较,如果不满足规则1,则与父元素替换(如下图所示)。

第一步

81de131b59fd81df918eec09f24f8a87.png

第二步

2f5a0d15c427a03f3a01427ca28b6812.png

第三步

194d03b9df7996aa94e1a7da8baeef69.png

二、取值操作

取最小值操作:

在最小堆中,拿出一个最小值,当然就是拿出第一个数啦~不过拿完以后树不就没有“头”了?

不用担心,我们可以把最后一个数放到头的位置,这样树的结构就不会改变,而且操作简单(因为是最后一个数)并且不会改变完全二叉树结构。

当然,因为是最后一个数,必然会出现不满足条件1的情况,所以我们需要把新的树头与子元素比较替换,下面是图片演示:

假设我们有一个原始的最小堆如下所示,接下来我们要取最小值:

aa0cbcc9d5c98361a67cbf0accaae8b2.png

1d037f3097552ce99f70271f27022d1b.png

不过交换完很可能是不满足条件1的,那么我们就需要比较替换,替换规则是和两个子元素中最小的一个替换

f0277c8db4121a711a781d7731cedda5.png

89f25d11f42c2fe7a47667fe8d8c2739.png

由上面可以明白堆的插入与取值操作,那么我们接下来用代码实现最大堆的操作

最大堆实现操作步骤

首先创建一个堆的类

1、初始化一个空堆,使用数组来存放堆元素,节省存储

2、定义一个查找父结点的方法 get_parent_index 为插入,取值操作做准备

首先判断孩子结点下标:

当孩子结点下标为 0 时,证明此时孩子结点为根节点,根节点没有父结点,返回None

当孩子及诶点大于 当前堆的元素值时,证明此时没有该孩子结点,孩子结点不逊在,那么 该孩子结点没有父结点返回 None

当孩子结点有父结点时,利用位运算符 >> 求出当前孩子结点的父结点下标

3、定义交换两个索引值的方法 swap 方法,利用列表的下标,交换两个数值的位置

4、定义插入结点方法 insert 方法

先把元素放在最后面,然后往前依次堆化 (保证完全二叉树结构)
这里以大顶堆为例,如果插入元素比父结点大,则交换,直到最后

(1) 把新添加的结点插入数组的最后面

(2) 找到新添加(最后一个) 元素的索引

(3) 找到该元素的父结点下标

(4) 定义一个循环,判断当前孩子结点与父结点大小

若当孩子结点的值大于父结点时,不满足最大堆的条件,将孩子结点与父结点交换位置

交换后,子节点上移后,再次判断父结点下标,再次循环判断直到该元素成为堆顶,或小于父结点(对于大顶堆)

5、定义取值 删除堆顶元素 pop 方法

删除堆顶元素,然后将最后一个元素放在堆顶,在从上往下依次堆化,保证完全二叉树结构

(1) 找到堆顶元素

(2) 把最后一个结点放到堆顶

(3) 删除最后一个元素

(4) 从堆顶堆化,利用定义的 heapify 方法

(5) 返回删除的结点元素值

6、定义堆化 heapify 方法

从上往下堆化,从 index 开始堆化操作 (大顶堆)

最大堆代码实现

python

class Heap:def __init__(self):# 初始化一个空堆,使用数组来存放堆元素,节省存储self.data_list = []def get_parent_index(self,child_index : int): # child_index : 孩子结点下标"""返回父结点的下标"""if child_index == 0 or child_index > len(self.data_list) - 1:return Noneelse:return (child_index - 1) >> 1# 如果某个结点的孩子结点空缺,数组对应的位置也空缺# 假设一个父结点的下标是 parent ,左孩子的下标是  2*parent+1 ,右孩子下标是  2*parent+2# 左孩子的下标是 child,父结点的西下表是 (child - 1)/2def swap(self,index_a,index_b):'''交换两个索引对应的值:param index_a:  a索引:type index_a:  int:param index_b:  b索引:type index_b:  int:return::rtype:'''self.data_list[index_a],self.data_list[index_b] = self.data_list[index_b],self.data_list[index_a]def insert(self,data : int):"""先把元素放在最后面,然后往前依次堆化  (保证完全二叉树结构)这里以大顶堆为例,如果插入元素比父结点大,则交换,直到最后"""self.data_list.append(data) # 把新添加的结点插入数组的最后面curr_index = len(self.data_list) - 1 # 新添加(最后一个) 元素的索引curr_parent_index = self.get_parent_index(curr_index) # 找到该元素的父结点下标# 循环,直到该元素成为堆顶,或小于父结点(对于大顶堆)while curr_parent_index is not None and self.data_list[curr_parent_index] < self.data_list[curr_index]:self.swap(curr_parent_index,curr_index) # 利用 swap 交换操作curr_index = curr_parent_index # 结点上移curr_parent_index = self.get_parent_index(curr_parent_index) # 再次判断父结点def pop(self):"""删除堆顶元素,然后将最后一个元素放在堆顶,在从上往下依次堆化"""del_data = self.data_list[0] # 找到堆顶元素self.data_list[0] = self.data_list[-1] # 把最后一个结点放到堆顶del self.data_list[-1] # 删除最后一个元素self.heapify(0) # 从堆顶堆化,利用定义的 heapify 方法return del_data # 返回删除的元素def heapify(self,index):"""从上往下堆化,从 index 开始堆化操作 (大顶堆)"""size = len(self.data_list) - 1 # 数组的长度while True:mv_idx = index # mx_idx 代表最大值索引if 2 * index + 1 < size and self.data_list[2*index+1] > self.data_list[mv_idx]:mv_idx = 2 * index + 1 # 如果左孩子结点大于当前最大结点,最大值索引等于左孩子索引if 2 * index + 2 < size and self.data_list[2*index+2] > self.data_list[mv_idx]:mv_idx = 2 * index + 2 # 如果右孩子结点大于当前最大结点,最大值索引等于右孩子索引if mv_idx == index: # 如果当孩子结点与最大值索引相等时,证明此时循环完成,退出循环breakself.swap(mv_idx,index) #交换最大值和当前值index = mv_idx # 当前值等于这一轮的最大值结点if __name__ == '__main__':myheap = Heap()for i in range(10):myheap.insert(i + 1)print("建堆:",myheap.data_list)print("删除堆顶元素:",[myheap.pop() for i in range(10)])

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

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

相关文章

acer软件保护卡清除工具clear_如何清除 APT 缓存来回收宝贵的磁盘空间 | Linux 中国...

导读&#xff1a;在本教程中&#xff0c;我将解释什么是 APT 缓存、为什么会使用它、为什么你要清理它&#xff0c;以及关于清理 APT 缓存你应该知道的其他事情。本文字数&#xff1a;2132&#xff0c;阅读时长大约&#xff1a;3分钟https://linux.cn/article-12787-1.html作者…

检测正常和不正常图_医生提醒:激素正常不等于内分泌正常,带你走出内分泌失调误区...

内分泌失调是女性常见的问题&#xff0c;特别是压力较大的都市女性&#xff0c;常常因为内分泌失调而导致月经紊乱&#xff0c;同时皮肤状态也变得糟糕&#xff0c;让她们很是心烦。一旦怀疑自己是内分泌失调&#xff0c;不少女性都会进行相应的激素检测&#xff0c;但如果检测…

antd 判断input输入内容是否大于_Python基础语法 | 代码规范amp;判断语句amp;循环语句...

Python基础语法代码的执行顺序从上到下从左到右代码规范模块名&#xff0c;包名&#xff0c;普通数据量一般小写字母&#xff0c;多个单词之间用 _ 连接不要用系统定义的名称&#xff0c;具有特殊意义的表示符&#xff0c;如:doc&#xff0c;txt之类的每行代码不易过长单个字母…

小米手环导出心率_这个功能有意思,小米11支持指纹检测心率,没有手环也不怕...

原标题&#xff1a;这个功能有意思&#xff0c;小米11支持指纹检测心率&#xff0c;没有手环也不怕昨晚&#xff0c;小米发布了新一代数字旗舰小米11&#xff0c;在处理器和屏幕等方面都做了升级&#xff0c;相比于这些重点&#xff0c;有一项新功能的介绍篇幅不是很多&#xf…

用单片机测量流体流速的_金属管转子流量计基本测量原理

金属管转子流量计的主体构件是一根金属材质的锥形测量管&#xff0c;测量元件是一个内置磁钢的转子&#xff08;或称浮子&#xff09;&#xff0c;故而得名。金属管的锥度通常在4左右&#xff0c;下端截面积略小于上端&#xff1b;转子直径略小于金属管内径&#xff0c;形成一个…

css如何调整红心样式_在JavaScript应用程序中包含CSS的多种方法「渡一」

原文链接&#xff1a;https://css-tricks.com/the-many-ways-to-include-css-in-javascript-applications/&#xff0c;作者&#xff1a;Dominic Magnifico如有翻译不准确&#xff0c;请多指正。欢迎来到这个在前端开发领域极具争议性的话题&#xff01;我相信读到这篇文章的大…

小新pro13 重装注意_新款小新pro 13注意什么?买前必读

导读&#xff1a;看到这一款本本&#xff0c;你的感觉是什么呢&#xff1f;精巧、美丽&#xff0c;性能强劲还是高分辨的屏幕呢&#xff1f;一起看一看2020款的联想(Lenovo)小新Pro13&#xff0c;要注意哪些事项&#xff1f;请听小编简单跟你唠几句~1、买联想小新pro的&#xf…

服务禁止方法_Linux禁止ping以及开启ping的方法

今天浏览一个网站&#xff0c;本着好奇的心态ping一下&#xff0c;发现不管是ping域名和IP都是不通的。这就比较郁闷了&#xff0c;后来百度后知道原来服务器是可以设置禁止ping的&#xff0c;看来是我孤陋寡闻了&#xff0c;接下来给大家分享一下服务器如何禁止ping。Linux默认…

java 多态判断非空_Java核心技术(四):继承

本章目录&#xff1a;一、类、超类和子类1.多态2.动态绑定3.阻止继承&#xff1a;final类和方法4.抽象类5.访问修饰符总结二、Object类&#xff1a;所有类的父类1.equals方法2.hashcode方法3.toString方法三、对象包装器与自动装箱四、反射1.Class类2.捕获异常3.利用反射分析类…

互相引用 spring_听说你还不知道Spring是如何解决循环依赖问题的?

作者&#xff1a;Vt前言Spring如何解决的循环依赖&#xff0c;是近两年流行起来的一道Java面试题。其实笔者本人对这类框架源码题还是持一定的怀疑态度的。如果笔者作为面试官&#xff0c;可能会问一些诸如“如果注入的属性为null&#xff0c;你会从哪几个方向去排查”这些场景…

打印多页时两边取消留白_办公必备技巧:Word打印技巧大全

打印是每一位办公族都要掌握的一项最基础的技能。平常在用WORD写作、对文章进行排版等&#xff0c;最终我们都是需要将其打印到纸张上。在打印中有着众多的操作技巧&#xff0c;如果你还不会&#xff0c;那今天易老师就来给你科普一下。本文目录第一部分&#xff1a;基础打印操…

中raise抛出异常_Python 异常处理知识点汇总,五分钟就能学会 !

异常处理在任何一门编程语言里都是值得关注的一个话题&#xff0c;良好的异常处理可以让你的程序更加健壮&#xff0c;清晰的错误信息更能帮助你快速修复问题。在Python中&#xff0c;和不分高级语言一样&#xff0c;使用了try/except/finally语句块来处理异常&#xff0c;如果…

easyexcel多个sheet导入_Java中Easypoi实现excel多sheet表导入导出功能

Easypoi简化了开发中对文档的导入导出实现&#xff0c;并不像poi那样都要写大段工具类来搞定文档的读写。第一步引入Easypoi依赖cn.afterturneasypoi-spring-boot-starter4.2.0Easypoi的注解使用说明(存留查看即可)第二步定义对应表格头数据对象实体类(注解的使用可以查阅上面的…

mysql 严格模式_MySQL 开启/关闭 严格模式(Strict Mode)

[广告&#xff1a;最高 2000 红包]阿里云服务器、主机等产品通用&#xff0c;可叠加官网常规优惠使用 | 限时领取查看 Mysql 是否开启严格模式&#xff1a;打开 MySQL 配置文件 my.cnf(windows为my.ini)。搜索 sql-mode 如果搜索不到就代表 非严格模式 。搜索到了就代表开启了严…

mysql 导入日期 0000_解决Excel导入MySQL日期为0000-00-00

最近在为客户做一个库存升级改造的项目&#xff0c;之前客户的数据管理全部是在Excel中操作&#xff0c;估计以前也是没有意识到数据量变大以后&#xff0c;工作会变得如此困难&#xff0c;基本上处于一个无法操作的程度了。于是我们将旧版本的Excel表格格式化以后&#xff0c;…

关于mysql优化_关于MySQL优化的几点总结

前言现如今&#xff0c;数据库的操作越来越成为整个应用的性能瓶颈了&#xff0c;这点对于Web应用尤其明显。所以&#xff0c;我整理了MySQL优化的几点建议&#xff0c;希望这些优化技巧对您有用&#xff0c;总结不到的&#xff0c;欢迎大家补充。SQL执行慢的原因网络速度慢&am…

ubuntu忘记mysql密码_ubuntu 忘记mysql 密码解决方法

一段时间没有用mysql数据库&#xff0c;今天突然需要使用&#xff0c;结果忘记密码&#xff0c;google了下找到的解决方法&#xff0c;就顺便记录下&#xff0c;下次碰到就不需要这么麻烦了1、输入命令 cat /etc/mysql/debian.cnf2、使用账号 debian-sys-maint 账号登录mysql密…

navicat mysql创建表_Navicat for MySQL如何创建数据表

Navicat for MySQL是针对MySQL数据库管理而研发的管理工具,创建数据表是其最基本操作,本教程将详解Navicat for MySQL创建数据表的方法。 步骤一:新建连接 运行Navicat数据库管理工具,连接本地数据库。点击左上角“文件”或者工具栏“连接”图标,创建自己的数据库连接。Na…

mysql-5.1.73-8.el6_在centos中安装mysql详细步骤说明

Last login: Sun Dec 24 04:55:59 20171、安装依赖[rootnode001 ~]# yum install -y perlLoaded plugins: fastestmirrorLoading mirror speeds from cached hostfilebase | 3.7 kB 00:00extras | 3.4 kB 00:00updates | 3.4 kB 00:00Setting up Install ProcessPackage 4:perl…

lte盲重定向_LTE重选、切换、重定向的区别

【资料名称】&#xff1a;LTE重选、切换、重定向的区别【资料作者】&#xff1a;A【资料日期】&#xff1a;20150916【资料语言】&#xff1a;中文【资料格式】&#xff1a;DOC/DOCX【资料目录和简介】&#xff1a;这里主要简单阐述了LTE系统的小区重选、切换、重定向的区别小区…