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,一经查实,立即删除!

相关文章

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

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

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…

6款帮助 滚动视差jquery插件

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

EBS 多组织访问设置

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

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

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

制作简单的java应用程序_使用exe4j工具制作简单的java应用程序

首先需要下载exe4j工具并进行安装&#xff0c;下面是利用exe4j工具制作应用程序的步骤。1.首先将工程导出为可运行的jar包&#xff0c;选择extract required libralies into generated java&#xff0c;会将引用到的jar包也打到里面。右键java工程--export--java--runnable jar…

MVC的传递数据的方法

1、使用ViewBag 1 #region 0.2 Action方法 ActionResult Index2()2 /// <summary>3 /// Action方法4 /// </summary>5 /// <returns></returns>6 public ActionResult Index2()7 {8 …

java 找不到构造函数_JAVA找不到符号构造函数

JAVA找不到符号构造函数关注:52 答案:2 mip版解决时间 2021-02-05 09:13提问者彼岸独舞2021-02-05 00:06class Rect{private double length;private double width;public Rect(double length,double width){this.widthwidth;this.lengthlength;}public double getLength(){re…

SRF之数据访问

数据访问组件实现实体类和数据表映射、SQL语句配置执行、动态sql语句等功能&#xff0c;ORM方式能实现简单的对象和表的映射&#xff08;配置类似hibernate&#xff09;&#xff0c;但比较单一&#xff08;不支持一对多、多对多的情况&#xff09;&#xff0c;下边不做介绍&…

POJ 2054 Color a Tree

贪心。。。。 Color a TreeTime Limit: 1000MS Memory Limit: 30000KTotal Submissions: 6647 Accepted: 2249Description Bob is very interested in the data structure of a tree. A tree is a directed graph in which a special node is singled out, called the "ro…

php xml 空格,php闭合标签输出多余空行使xml页面显示错误的处理

在PHP官方文档中&#xff0c;曾经指出最好不要再结尾添加?>结束标记。但我们编程的习惯和使用的IDE都会为我们自动建立php结束标记?>。这个标记使用在正常情况下是不影响程序的运行的。尤其在早期的php4中&#xff0c;这种标记使用不当也不会影响最后的输出。但我最近遇…

Oil Deposits

hdu1241:http://acm.hdu.edu.cn/showproblem.php?pid1241 题意&#xff1a;就是找出有多少块有石油的区域&#xff0c;就是数组中的,这边相邻指的是是周围的八个位置。 题解&#xff1a; dfs&#xff0c;从一块油田的位子开始&#xff0c;朝着与他相邻的8个方向收索&#xff…

java.io.FileNotFoundException:/mnt/sdcard/......(Permission denied)

今天在实现下载模块的时候&#xff0c;从服务器下载apk安装的时候总是不成功。 打开LogCat查看日志&#xff0c;发现在访问sdcard的时候出现Permission denied的情况。 百度之后发现原因是没有添加权限。 解决办法是在Manifest文件里添加&#xff1a; “<uses-permission an…

详解.NET IL代码(一)

本文主要介绍IL代码&#xff0c;内容大部分来自网上&#xff0c;进行整理合并的。 一、IL简介 为什么要了解IL代码&#xff1f; 如果想学好.NET&#xff0c;IL是必须的基础&#xff0c;IL代码是.NET运行的基础&#xff0c;当我们对运行结果有异议的时候&#xff0c;可以通过IL代…

CentOS yum安装mcrypt详细图解教程[linux]

在Linux的发行版CentOS 6.3 系统下&#xff0c;LAMP(LinuxApacheMysqlphp)环境搭建好后发现PHPMyadmin提示 “无法载入mcrypt模块” 的错误感觉很不爽&#xff0c;就尝试着使用yum安装提示找不到模块。如下为执行过程&#xff1a; [rootptr228 ~]# yum install php-mcrypt Sett…

[算法 笔记]2014年去哪儿网 开发笔试(续)第一题BUG修正

上一篇的blog地址为&#xff1a;http://www.cnblogs.com/life91/p/3313868.html 这几天又参加了一个家公司的笔试题&#xff0c;在最后的编程题中竟然出现了去哪儿网开发的第一题&#xff0c;也就是简化路径值。但是这次做题后&#xff0c;我发现我上次写的那个简化源码有很多问…

java封装264成flv,将H.264封装为FLV格式-Go语言中文社区

本文将介绍如何将H.264封装成flv格式。在看本文之间&#xff0c;建议先看一看下面两篇文章&#xff1a;首先说一说构建一个FLV文件需要什么&#xff1f;FLV Header FLv script tag FLV Video tag FLV Audio tag由于这里只是封装H.264&#xff0c;所以不包括Audio tag。下面将…

[转]iis7.5+win2008 出现 HTTP Error 503. The service is unavailable.

解决&#xff1a; 应用程序池启动32位应用程序 设置托管管道为集成 &#xff08;仍然有问题&#xff09; 试试以下方法&#xff1a; http://phpwind.me/1222.html 楼主 发表于: 2011-11-26 图片:123.png 访问网站之前 应用程序池是开启的 访问后 网页报503 service unavailabl…

sublime php运行环境,sublime php 运行环境

sublime php 运行环境sublime php 运行环境有时候需要用运行一段 PHP 代码&#xff0c;比如测试某个函数返回值等等&#xff0c;如果启动Http Server&#xff0c;再打开浏览器&#xff0c;那黄花菜都凉了。我们可以在 Sublime Text 3 中创建 php 的 build system&#xff0c;这…