heap python_数据结构-堆(Heap) Python实现

堆(Heap)可以看成近似完全二叉树的数组,树中每个节点对应数组中一个元素。除了最底层之外,该树是完全充满的,最底层是从左到右填充的。

堆包括最大堆和最小堆:最大堆的每一个节点(除了根结点)的值不大于其父节点;最小堆的每一个节点(除了根结点)的值不小于其父节点。

本文以最大堆为例,先直观感受一下堆的样子:

图片来源

b2f75d40a2cf

最大堆

树中节点内的值表示存储的值,节点旁边的值表示该节点在数组中的下标。

观察上图不难发现,对于一个给定节点的下标i,其父节点、左孩子、右孩子的下标为:

parent(i): (i + 1) // 2 - 1

left(i): i * 2 + 1

right(i): i * 2 + 2

其中“//”表示除法后只取整数部分。

对于一个给定的数组,如何转化为堆呢?

对于一个任意节点,如果该节点大于左孩子和右孩子,则该节点无需移动。否则,和左右孩子中较大的那个交换位置,于是该节点满足大于左右孩子了,但是刚被交换了的孩子节点需要继续比较它的左右孩子......整个过程递归进行下去,我们可以轻松计算出:对于根节点,在进行转化成堆的过程中,最多需要交换h次(h为树的高度),对于树种的每个节点,如果都进行此操作,则整个过程的时间复杂度为:O(nlogn)。(n为节点数,logn≈h)

代码如下:

def heapify(self):

for i in range((len(self.heap) + 1) // 2 - 1, -1, -1):

self.max_heapify_top(i)

def max_heapify_top(self, i):

"""

从上到下

O(logn)

"""

left = i * 2 + 1

right = i * 2 + 2

if left < len(self.heap) and self.heap[left] > self.heap[i]:

largest = left

else:

largest = i

if right < len(self.heap) and self.heap[right] > self.heap[largest]:

largest = right

if largest != i:

self.heap[largest], self.heap[i] = self.heap[i], self.heap[largest]

self.max_heapify_top(largest)

以上代码中heapify函数从(len(self.heap) + 1) // 2 - 1到0进行遍历,是因为树中的叶子节点没有孩子,因此可以看成满足堆的性质,所以无需进行heapify,所以从非叶子节点开始遍历,节约时间。

如何从堆中弹出和插入元素呢?

先说弹出。由于是最大堆,因此每次弹出需要弹出最大的元素,那就是根节点,如何弹出后还保持堆的性质呢。具体做法是:先将树中根节点和最后一个节点交换位置,对应数组中就是第一个元素和最后一个元素交换位置,然后弹出最后一个元素,在对交换位置后的根节点进行heapify,这样弹出了最大元素,同时也保持了堆的性质。

代码如下:

def pop(self):

"""

O(logn)

"""

self.heap[0], self.heap[len(self.heap) - 1] = self.heap[len(self.heap) - 1], self.heap[0]

value = self.heap.pop()

self.max_heapify_top(0)

return value

插入元素。

先将元素放在树的末尾,也是数组的末尾,再按照自下而上的顺序依次比较与父节点的大小关系,自下而上进行heapify。

代码如下:

def push(self, value):

"""

O(logn)

"""

self.heap.append(value)

self.max_heapify_button(len(self.heap) - 1)

def max_heapify_button(self, i):

"""

从下到上

O(logn)

"""

parent = (i + 1) // 2 - 1

if parent >= 0 and self.heap[parent] < self.heap[i]:

smallest = parent

else:

smallest = i

if smallest != i:

self.heap[smallest], self.heap[i] = self.heap[i], self.heap[smallest]

self.max_heapify_button(smallest)

整个堆的实现代码为:

class Heap:

def __init__(self, heap=[]):

self.heap = heap

def heapify(self):

for i in range((len(self.heap) + 1) // 2 - 1, -1, -1):

self.max_heapify_top(i)

def max_heapify_top(self, i):

"""

从上到下

O(logn)

"""

left = i * 2 + 1

right = i * 2 + 2

if left < len(self.heap) and self.heap[left] > self.heap[i]:

largest = left

else:

largest = i

if right < len(self.heap) and self.heap[right] > self.heap[largest]:

largest = right

if largest != i:

self.heap[largest], self.heap[i] = self.heap[i], self.heap[largest]

self.max_heapify_top(largest)

def max_heapify_button(self, i):

"""

从下到上

O(logn)

"""

parent = (i + 1) // 2 - 1

if parent >= 0 and self.heap[parent] < self.heap[i]:

smallest = parent

else:

smallest = i

if smallest != i:

self.heap[smallest], self.heap[i] = self.heap[i], self.heap[smallest]

self.max_heapify_button(smallest)

def pop(self):

"""

O(logn)

"""

self.heap[0], self.heap[len(self.heap) - 1] = self.heap[len(self.heap) - 1], self.heap[0]

value = self.heap.pop()

self.max_heapify_top(0)

return value

def push(self, value):

"""

O(logn)

"""

self.heap.append(value)

self.max_heapify_button(len(self.heap) - 1)

再说堆排序呢?对于一个任意的数组,进行构建堆之后,再按照顺序依次弹出堆中的元素,便得到了有序的数组。更神奇的是,在数组末尾添加一个指针,便可实现数组的原地排序(不需要额外空间)。堆排序的时间复杂度为:O(nlogn),空间复杂度为:O(1)

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

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

相关文章

多个 App 间启动

http://developer.nokia.com/: URI associations for Windows Phone http://msdn.microsoft.com/: Auto-launching apps using file and URI associations for Windows Phone 8 代码示例转载于:https://www.cnblogs.com/sirkevin/p/3325035.html

im4java 文档_im4java学习---阅读documentation文档

Utilities----im提供的一些工具类①、读取图片文件信息---Info类我们之前的做法&#xff1a;op.format("width:%w,height:%h,path:%d%f,size:%b%[EXIF:DateTimeOriginal]");IdentifyCmd identifyCmd new IdentifyCmd(useGM);使用工具类Info&#xff1a;Info imageIn…

函数体中定义的结构体和类型

源代码&#xff1a; 1 #include <stdio.h>2 struct smonth // point 13 {4 int a;5 int b;6 };7 8 int func1()9 { 10 struct smonth{ 11 int a; 12 int b; 13 }; 14 15 ty…

java listview用法_Java ListView.setMultiChoiceModeListener方法代码示例

import android.widget.ListView; //导入方法依赖的package包/类Overridepublic void onActivityCreated(Nullable Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);lAdapter new LabelAdapter(getActivity(), null, 0);setListAdapter(lAdapter);g…

预编译指令与宏定义

#if #elif [defined(), !defined()] #else #ifdef #ifndef #endif // 条件编译 /* 头文件防止多次被包含 */ #ifndef ZLIB_H #define ZLIB_H#endif /* ZLIB_H *//* 用C方式来修饰函数与变量 */ #ifdef __cplusplus extern "C" { #endif int add(int a, …

java mock server_java – 使用MockRestServiceServer模拟REST调用

我正在尝试编写一个JUnit测试用例,用于测试辅助类中的方法.该方法使用REST调用外部应用程序,这是我试图在JUnit测试中模拟的调用.辅助方法使用Spring的RestTemplate进行REST调用.在我的测试中,我创建了一个模拟REST服务器并模拟REST模板并将它们实例化为&#xff1a;Beforepubl…

BZOJ 2597 剪刀石头布(最小费用最大流)(WC2007)

Description 在一些一对一游戏的比赛&#xff08;如下棋、乒乓球和羽毛球的单打&#xff09;中&#xff0c;我们经常会遇到A胜过B&#xff0c;B胜过C而C又胜过A的有趣情况&#xff0c;不妨形象的称之为剪刀石头布情况。有的时候&#xff0c;无聊的人们会津津乐道于统计有多少这…

java swt最小化到托盘_SWT 中实现最小化到托盘图标,并只能通过托盘的弹出菜单关闭程序...

package com.unmi;import org.eclipse.swt.*;import org.eclipse.swt.events.*;import org.eclipse.swt.graphics.*;import org.eclipse.swt.widgets.*;/*** SWT 3.0 开始引入了 Tray&#xff0c;可以在系统栏放置你的程序图标了* 本程序实现的功能有四&#xff1a;* 1. 点击窗…

HDU 1476 Sudoku Killer

Sudoku Killer Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3367 Accepted Submission(s): 1063 Problem Description自从2006年3月10日至11日的首届数独世界锦标赛以后&#xff0c;数独这项游戏越来越受到…

java .net 互通redis_C# servicestack.redis 互通 java jedis

本文是基于jedis的一致性环哈希来修改的&#xff0c;.net选的是servicestack.redis组件来修改无奈两个组件都有各自的一致性环哈希算法&#xff0c;不兼容&#xff0c;那就选一个作为标准&#xff0c;修改另一个咯。本文选择jedis的一致性环哈希作为标准&#xff0c;进而修改.n…

java 多重压缩下载_Java 多文件边压缩边下载

有时我们希望在后台实时生成文件并下载到客户端GetMapping(value "download")public void download(HttpServletResponse response) {try(OutputStream outputStream response.getOutputStream();ZipOutputStream zipOutputStream new ZipOutputStream(outputStre…

wdatepicker使用指南

wdatepicker使用指南 http://blog.csdn.net/zengxin2008/article/details/7248964#t63posted on 2013-09-22 15:45 moonfans 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/moonfans/p/3333251.html

纵表、横表互转的SQL

纵表、横表互转的SQL By&#xff1a;大志若愚 1、建表&#xff1a; 纵表结构 Table_A create table Table_A (姓名 varchar(20),课程 varchar(20),成绩 int ) insert into Table_A(姓名,课程,成绩) values(张三,语文,60) insert into Table_A(姓名,课程,成绩) values(张三,数学…

java按照商品价格排序_按照指定的类型排序

比如有三本书&#xff0c;书名和价格分别如下&#xff1a;《猎物》18.4元、《大明王朝》59.0元、《快乐密码》25.0元。前几天的一篇文章中讲到按照中文拼音进行排序&#xff0c;这里如果想按照价格排序的话怎么办&#xff1f;其实这里就牵涉到在Java中怎样对对象进行排序处理&a…

6款帮助 滚动视差jquery插件

在网页设计中&#xff0c;视差滚动&#xff08;Parallax Scrolling&#xff09;是当下流行的网页设计技术&#xff0c;通过让多层背景以不同的速度或者不同的方向移动来形成非常有趣的 3D 运动效果。下面是一些运用视差滚动效果的优秀网页案例&#xff1a; 视差&#xff08;Pa…

java i线程安全吗_Java中 i++ 是线程安全的么?为什么?

问题在 int i 0; i i; 语句中&#xff0c;i i是线程安全的么&#xff1f;如果不安全&#xff0c;请说明上面操作在JVM中的执行过程&#xff0c;为什么不安全&#xff1f;说出JDK中哪个类能达到以上的效果&#xff0c;并且是线程安全而且高效的&#xff0c;简述其原理。回答语…

EBS 多组织访问设置

如果想让你的职责下为单组织模式&#xff0c;那么你在Profile下只设置MO: Operating Unit的值&#xff0c;MO: Operating Unit提供只访问一个单独的OU。如果你想让你的职责下为多组织模式&#xff0c;你需要设置MO: Security Profile&#xff0c;MO: Security Profile提供多组织…

java第k小元素_java – 如何从对象列表中提取K“最小”元素?

我会对清单进行排序.然后,我将创建一个包含这10个最小对象的列表,并更改原始列表list1以包含其余对象.就像是&#xff1a;Collection.sort(list1);ArrayList yourSmallestElements (ArrayList)(list1.sublist(0, 9).clone());list1.removeAll(yourSmallestElements);注意&…

JQuery学习系列总结—菜单制作

1、页面中的菜单项可以通过嵌套的ul和li来表示 2、菜单最外层为ul&#xff0c;一层每个主菜单放在一个li中&#xff0c;如果有子菜单&#xff0c;在这个主菜单的li中建立新的ul&#xff0c;再依次嵌套即可构建多层的菜单 3、浏览器中ul和li元素默认情况下文字前都有圆点标识符&…

mysql 大量列 动态变量_aardio动态mysql变量设置

aardio动态mysql变量设置aardio动态mysql变量设置废话不多说&#xff0c;直接开始干活&#xff01;从上午度娘到现在&#xff01;终于有点结果&#xff01;需求是从数据库读取数据&#xff0c;根据条件(变量)直接上代码&#xff0c;如有任何问题&#xff0c;欢迎老铁指正&#…