数据结构:堆(Heap)

JavaScript08

数据结构:堆(Heap),第1张

堆就是用数组实现的二叉树,所以它没有使用父指针或者子指针。堆根据“堆属性”来排序,“堆属性”决定了树中节点的位置。

堆的常用方法:

堆分为两种: 最大堆 和 最小堆 ,两者的差别在于节点的排序方式。

在最大堆中,父节点的值比每一个子节点的值都要大。在最小堆中,父节点的值比每一个子节点的值都要小。这就是所谓的“堆属性”,并且这个属性对堆中的每一个节点都成立。

例子:

这是一个最大堆,,因为每一个父节点的值都比其子节点要大。 10 比 7 和 2 都大。 7 比 5 和 1 都大。

根据这一属性,那么最大堆总是将其中的最大值存放在树的根节点。而对于最小堆,根节点中的元素总是树中的最小值。堆属性非常有用,因为堆常常被当做优先队列使用,因为可以快速地访问到“最重要”的元素。

堆并不能取代二叉搜索树,它们之间有相似之处也有一些不同。我们来看一下两者的主要差别:

节点的顺序。 在二叉搜索树中,左子节点必须比父节点小,右子节点必须必比父节点大。但是在堆中并非如此。在最大堆中两个子节点都必须比父节点小,而在最小堆中,它们都必须比父节点大。

内存占用。 普通树占用的内存空间比它们存储的数据要多。你必须为节点对象以及左/右子节点指针分配内存。堆仅仅使用一个数据来存储数组,且不使用指针。

平衡。 二叉搜索树必须是“平衡”的情况下,其大部分操作的复杂度才能达到 O(log n) 。你可以按任意顺序位置插入/删除数据,或者使用 AVL 树或者红黑树,但是在堆中实际上不需要整棵树都是有序的。我们只需要满足堆属性即可,所以在堆中平衡不是问题。因为堆中数据的组织方式可以保证 O(log n) 的性能。

搜索。 在二叉树中搜索会很快,但是在堆中搜索会很慢。在堆中搜索不是第一优先级,因为使用堆的目的是将最大(或者最小)的节点放在最前面,从而快速的进行相关插入、删除操作。

用数组来实现树相关的数据结构也许看起来有点古怪,但是它在时间和空间上都是很高效的。

我们准备将上面例子中的树这样存储:

就这么多!我们除了一个简单的数组以外,不需要任何额外的空间。

如果我们不允许使用指针,那么我们怎么知道哪一个节点是父节点,哪一个节点是它的子节点呢?问得好!节点在数组中的位置index 和它的父节点以及子节点的索引之间有一个映射关系。

如果 i 是节点的索引,那么下面的公式就给出了它的父节点和子节点在数组中的位置:

注意 right(i) 就是简单的 left(i) + 1 。左右节点总是处于相邻的位置。

我们将写公式放到前面的例子中验证一下。

复习一下,在最大堆中,父节点的值总是要大于(或者等于)其子节点的值。这意味下面的公式对数组中任意一个索引 i 都成立:

可以用上面的例子来验证一下这个堆属性。

如你所见,这些公式允许我们不使用指针就可以找到任何一个节点的父节点或者子节点。事情比简单的去掉指针要复杂,但这就是交易:我们节约了空间,但是要进行更多计算。幸好这些计算很快并且只需要 O(1) 的时间。

理解数组索引和节点位置之间的关系非常重要。这里有一个更大的堆,它有15个节点被分成了4层:

图片中的数字不是节点的值,而是存储这个节点的数组索引!这里是数组索引和树的层级之间的关系:

由上图可以看到,数组中父节点总是在子节点的前面。

注意这个方案与一些限制。你可以在普通二叉树中按照下面的方式组织数据,但是在堆中不可以:

在堆中,在当前层级所有的节点都已经填满之前不允许开是下一层的填充,所以堆总是有这样的形状:

小测验,假设我们有这样一个数组:

这是一个有效的堆吗?答案是 yes !一个从低到高有序排列的数组是以有效的最小堆,我们可以将这个堆画出来:

堆属性适用于每一个节点,因为父节点总是比它的字节点小。(你也可以验证一下:一个从高到低有序排列的数组是一个有效的最大堆)

如果你好奇,这里有更多的公式描述了堆的一些确定属性。你不需要知道这些,但它们有时会派上用场。 可以直接跳过此部分!

树的 高度 是指从树的根节点到最低的叶节点所需要的步数,或者更正式的定义:高度是指节点之间的边的最大值。一个高度为 h 的堆有 h+1 层。

下面这个对的高度是3,所以它有4层:

如果一个堆有 n 个节点,那么它的高度是 h = floor(log2(n)) 。这是因为我们总是要将这一层完全填满以后才会填充新的一层。上面的例子有 15 个节点,所以它的高度是 floor(log2(15)) = floor(3.91) = 3 。

如果最下面的一层已经填满,那么那一层包含 2^h 个节点。树中这一层以上所有的节点数目为 2^h - 1 。同样是上面这个例子,最下面的一层有8个节点,实际上就是 2^3 = 8 。前面的三层一共包含7的节点,即: 2^3 - 1 = 8 - 1 = 7 。

所以整个堆中的节点数目为:* 2^(h+1) - 1*。上面的例子中, 2^4 - 1 = 16 - 1 = 15

叶节点总是位于数组的 floor(n/2) 和 n-1 之间。

有两个原始操作用于保证插入或删除节点以后堆是一个有效的最大堆或者最小堆:

shiftUp 或者 shiftDown 是一个递归的过程,所以它的时间复杂度是 O(log n)

基于这两个原始操作还有一些其他的操作:

上面所有的操作的时间复杂度都是 O(log n) ,因为 shiftUp 和 shiftDown 都很费时。还有少数一些操作需要更多的时间:

堆还有一个 peek() 方法,不用删除节点就返回最大值(最大堆)或者最小值(最小堆)。时间复杂度 O(1)

我们通过一个插入例子来看看插入操作的细节。我们将数字 16 插入到这个堆中:

堆的数组是: [ 10, 7, 2, 5, 1 ] 。

第一股是将新的元素插入到数组的尾部。数组变成:

相应的树变成了:

16 被添加最后一行的第一个空位。

不行的是,现在堆属性不满足,因为 2 在 16 的上面,我们需要将大的数字在上面(这是一个最大堆)

为了恢复堆属性,我们需要交换 16 和 2 。

现在还没有完成,因为 10 也比 16 小。我们继续交换我们的插入元素和它的父节点,直到它的父节点比它大或者我们到达树的顶部。这就是所谓的 shift-up ,每一次插入操作后都需要进行。它将一个太大或者太小的数字“浮起”到树的顶部。

最后我们得到的堆:

现在每一个父节点都比它的子节点大。

我们将这个树中的 (10) 删除:

现在顶部有一个空的节点,怎么处理?

当插入节点的时候,我们将新的值返给数组的尾部。现在我们来做相反的事情:我们取出数组中的最后一个元素,将它放到树的顶部,然后再修复堆属性。

现在来看怎么 shift-down (1) 。为了保持最大堆的堆属性,我们需要树的顶部是最大的数据。现在有两个数字可用于交换 7 和 2 。我们选择这两者中的较大者称为最大值放在树的顶部,所以交换 7 和 1 ,现在树变成了:

继续堆化直到该节点没有任何子节点或者它比两个子节点都要大为止。对于我们的堆,我们只需要再有一次交换就恢复了堆属性:

绝大多数时候你需要删除的是堆的根节点,因为这就是堆的设计用途。

但是,删除任意节点也很有用。这是 remove() 的通用版本,它可能会使用到 shiftDown 和 shiftUp 。

我们还是用前面的例子,删除 (7) :

[图片上传失败...(image-d46ac4-1534077058042)]

对应的数组是

你知道,移除一个元素会破坏最大堆或者最小堆属性。我们需要将删除的元素和最后一个元素交换:

最后一个元素就是我们需要返回的元素;然后调用 removeLast() 来将它删除。 (1) 比它的子节点小,所以需要 shiftDown() 来修复。

然而,shift down 不是我们要处理的唯一情况。也有可能我们需要 shift up。考虑一下从下面的堆中删除 (5) 会发生什么:

现在 (5) 和 (8) 交换了。因为 (8) 比它的父节点大,我们需要 shiftUp() 。

解决webpack打包、编译、热更新Node内存不足问题_node内存不够_Vgb...

既然知道了问题所在,那么就好解决了,面向百度编程,百度搜索如何解决Node运行内存不足的问题马上就有了解决办法,increase-memory-limit可以提高Node占用内存。npm i -g increase-memory-limit安装包,然后在项目目录执行increase-memory-limit,...

继续访问

node打包内存不足问题解决方式:Allocation failed - JavaScript heap out...

直接在node后面写上--max_old_space_size=4096就好了,我这里设置的内存大小是4G,这个具体的大小可以根据自己的项目情况来设置就好了。然后再重新运行npm run build就可以正常打包构建了。

继续访问

gulp-htmlparser:使用 gulp 将 html 解析为 js 对象

#gulp-htmlparser 插件解析HTML用 包裹 gulp-htmlparser 描述 使用 gulp 将 html 解析为 js 对象 节点版本 >= 0.9 吞咽版 3.x 用法 安装 npm install gulp-htmlparser --save ##例子 var gulp = require ( 'gulp' ) var gparser = require ( 'gulp-htmlparser' ) gulp . task ( 'task' , function ( ) { gulp . src ( 'normal.html' ) . pipe ( gparser ( ) ) . pipe ( gulp . dest ( './' ) ) } ) gulp . task ( 'default' , 'task' )

node 内存 溢出 插件

版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。 现象描述 昨天用webpack打包Vue的项目时,node内存溢出而停止build项目,即是项目构建过程中频繁报内存溢出:FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory。并且打包速度相当慢...

继续访问

npm命令运行时报错_npm命令报错整理_我自来去的博客

二. 内存溢出内存不足 描述 远程连接win32位的服务器 在项目目录下执行打包命令 npm run build 报以上错误内容 内存溢出 内存不足 解决一 修改package.json中的内存大小 修改package.json文件中size的大小,然后重新执行打包命令 ...

继续访问

vscode执行npm时的一些错误及处理_蓝色格子的博客

这个原因是JavaScript堆内存不足。 FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory 1 2.2、解决 通过安装increase-memory-limit插件。命令:npm install -g increase-memory-lim...

继续访问

前端项目打包出现JavaScript堆内存不足、启动也会内存溢出解决办法\increase-memory-limit‘ 不是内部或外部命令,

打包出现JavaScript堆内存不足 最近打包遇到这种报错 Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory 以及 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 解决方法如下: 1.从网上搜索的资料试了一下,不大好用,不过也照做了 修改 package

继续访问

最新发布 npm 打包报错JavaScript heap out of memory(亲测可行)

npm 打包报错JavaScript heap out of memory(亲测可行)

继续访问

npm运行项目提示JavaScript heap out of memory(堆栈内存溢出问题)解决方案

1、堆栈内存溢出问题 npm ERR! code ELIFECYCLE npm ERR! errno 134 npm ERR! [email protected] dev: `vue-cli-service serve` npm ERR! Exit status 134 npm ERR! npm ERR! Failed at the [email protected] dev script. npm ERR! This is probably not a proble

继续访问

npm执行报内存溢出,内存不够很使用

您需要增加节点允许的内存量。 您可以通过以下方式在全局范围内执 打开一个cmd窗口 跑 setx NODE_OPTIONS --max_old_space_size=10240 针对本地调试使用。 关闭所有cmd /代码编辑器 重新打开cmd并再次运行节点命令(npm等) ...

继续访问

npm 执行中遇到的问题

ubuntu@ip-10-200-100-47:~/pinpoint-backend$ npm run build [email protected] prebuild /home/ubuntu/pinpoint-backend >rimraf dist [email protected] build /home/ubuntu/pinpoint-b...

继续访问

vue3+vite+ts打包时遇到的问题以及“优化”,JavaScript heap out of memory(错误:内存不足)等

如果用了element plus可能打包会出现这个报错。在tsconfig.json里加这代码就行。vue3+vite+ts打包时报错。

继续访问

npm run dev/build内存溢出解决方法,亲测有效(JavaScript heap out of memory)

npm run dev内存溢出解决方案

继续访问

vue项目运行时报内存溢出:JavaScript heap out of memory

原文链接:https://blog.csdn.net/u014028247/article/details/120198702 ==== JS stack trace ========================================= 0: ExitFrame [pc: 000002AACBF079E0] Security context: 0x00b4d151e6e9 <JSObject>1: byteLength(aka byteLength) [00

继续访问

gulp html 缓存,gulp解决浏览器缓存问题

给请求的文件加上唯一的版本号,这样浏览器就会加载新文件,防止因缓存产生的问题。下面是用gulp-rev生成md5签名,构建好的文件名会加上md5签名,同时生成一个json用来保存文件名路径对应关系。安装插件npminstall--save-devgulpnpminstall--save-devgulp-revnpminstall--save-devgulp-rev-collect...

继续访问

npm run build 报错 JavaScript heap out of memory &node -- max-old-space-size=4096不是内部或外部命令

npm run build 报错 JavaScript heap out of memory node -- max-old-space-size=4096不是内部或外部命令

继续访问

nodejs运行时 内存不足解决方案

找到nodejs运行配置文件目录 window下目录位置 C:\Users\39716(用户名)\AppData\Roaming\npm 找到内存不足发生的环境比如 webpack 打开webpack.cmd 添加 --max_old_space_size=4096 @IF EXIST "%~dp0\node.exe" ( "%~dp0\node.exe" "%~dp0\n...

继续访问

JS stacktrace--解决运行npm run serve 后报错,node内存溢出问题

拉去vue项目,运行npm run serve 后,报错如下 <--- JS stacktrace --->==== JS stack trace ========================================= 0: ExitFrame [pc: 0000002919A5C5C1] Security context: 0x02b9c119e6e9 <JSObject>1: _send [0000016FEC87BBF1] [intern

继续访问

node:内存溢出(报错:CALL_AND_RETRY_LAST分配失败-JavaScript堆内存不足)

描述:项目运行npm run dev 运行一定次数(我这里只能保存一次,第二次保存就报错,需要重新运行npm run dev,很耗费时间)后报错 报错:CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 翻译:CALL_AND_RETRY_LAST分配失败-JavaScript堆内存不足 进过各种搜索,找到关于问题的解决方法—node内存溢出 解决方法: CMD,进入命令行 复制粘贴命令:setx NODE_OPTION

继续访问

npm run build打包提示heap out of memory

npm打包报 heap out of memory的解决办法。

继续访问

运行npm start报错堆内存不足

报错 解决: "scripts": { "start": "node --max-old-space-size=4096 dev.js", "build": "webpack --progress --profile --colors --config webpack.prod.config.js", "test": "echo \"Error: no test...

继续访问

node内存溢出(报错:CALL_AND_RETRY_LAST分配失败-JavaScript堆内存不足)

描述:项目运行npm run dev 运行一定次数(我这里只能保存一次,第二次保存就报错,需要重新运行npm run dev,很耗费时间)后报错 报错:CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 翻译:CALL_AND_RETRY_LAST分配失败-JavaScript堆内存不足 进过各种搜索,找到关于...

继续访问

热门推荐 执行 npm 命令时报错:Allocation failed - JavaScript heap out of memory

执行 npm 命令时报错: FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory 原因是 JavaScript堆内存不足,Node 是基于V8引擎,在 Node 中通过 JavaScript 使用内存时只能使用部分内存(64位系统下约为1.4 GB),如果内存不足,可以用下面方法来放宽V8默认的内存限制。 法一:添加参数--max_old_spa.

继续访问

npm 报错内存不足

node.js