为什么两个不同的概念都被称为“堆”?


170

为什么将运行时堆用于C风格语言中的动态内存分配,并将数据结构都称为“堆”?有关系吗?


4
我今天在研究数据结构时想知道这一点。
MitMaro


3
转到英语词典并计算“运行”下的条目数。40多个条目中有多少个适用于计算机?:)
jmucchiello


此处有一篇有关wrt运行时堆的相关文章用于动态内存分配。
RBT

Answers:


77

唐纳德·克努斯(Donald Knuth)说(计算机编程艺术,第三版,第1卷,第435页):

几位作者于1975年左右开始将可用内存池称为“堆”。

他没有说出哪位作者,也没有提及任何特定的论文,但是他说与优先级队列相关的术语“堆”的使用是传统的含义。


11
池将比堆更好。

7
有趣。有人应该问他是否记得哪个作者。
法尔肯教授

27
Wikipedia声称这是因为Lisp在早期使用了一个堆(数据结构)来实现其内存存储。它没有说如何。它的参考文献是“ Thomas H. Cormen,Charles E. Leiserson,Ronald L. Rivest(1990):算法简介。麻省理工学院出版社/麦格劳-希尔”。
史蒂夫·杰索普

2
我对此没有参考,但我的猜测是,最初用于组织对打开的内存块的引用的数据结构是一个最小堆。似乎这至少是一种快速找到最小的内存块的不错的方法,该内存块将允许您存储要存储的数据更新:我说的听起来完全像是buddy块en.wikipedia.org/wiki/Dynamic_memory_allocation #巴迪%5Fblocks
威尔

4
@SteveJessop-在Corap,Leiserson,Rivest,Stein上检查Cormen-第三版(2009),在Heapsort章节的开头只说“ heap”一词最初是在heapsort的上下文中创造的,但此后一直指“垃圾收集存储”,例如Java和Lisp提供的编程语言。我们的堆数据结构不是垃圾收集的存储,每当我们在本书中提到堆时,我们都将指的是数据结构,而不是垃圾收集的一个方面。” CLRS-第2版也具有几乎完全相同的措词(没有迹象表明Lisp使用了堆)。
jimbob博士13年

64

它们具有相同的名称,但实际上并不相似(即使从概念上来说也是如此)。内存堆被称为堆,与将洗衣篮称为“衣服堆”的方式相同。此名称用于表示一个混乱的地方,可以随意分配和释放内存。数据结构(正如您所引用的Wikipedia链接所指出的)非常不同。


8
是的,我认为这正是他提出问题的依据:它们是不同的。那么为什么它们被称为同一件事-是否存在一些潜在的关系。
肖恩·欧文

9
我解释这个答案的方式是“不,没有潜在的关系”,所以它回答了这个问题。
劳伦斯·贡萨尔维斯(Lawrence Gonsalves),2009年

安德鲁正在回答。没有关系 只是一个巧合。内存堆更符合常规用法,因为分配内存就像“堆衣服”一样。然而,数据结构需要更大的想象力。这变成了一个非常有趣的“为什么”。名称来自事实节点,这些节点按其键排列,并且父节点键始终大于其子节点。
亚历山大贝尔

6
它们绝对无关。但是,将其称为“堆”的问题在于“堆的”对应对象(即“堆栈”)也是实际的堆栈。
2012年

1
我知道为什么将堆数据结构称为堆:因为它满足heap属性。但是为什么将堆属性称为此类?这对我来说毫无意义,因为像“重磅炸弹”这样的名称会更好。
Thomas Eding 2012年

31

碰撞这个名字很不幸,但并不是那么神秘。是一个很小的通用词,用来表示堆,集合,组等。在数据结构中使用该词早于(我很确定)内存池的名称。实际上,在我看来,对于后者而言,游泳池本来是更好的选择。表示垂直结构(如堆),适合数据结构,但不适合内存池。我们不认为内存池堆是分层的,而数据结构背后的基本思想是将最大的元素保持在堆(和子堆)的顶部。

堆的数据结构可以追溯到60年代中期。堆内存池,七十年代初。Wijngaarden至少早在1971年就使用了堆(意思是内存池)一词。在讨论Algol。

可能最早将用作数据结构是在七年前的
Williams,JWJ 1964中发现的。“算法232-堆排序”,ACM通讯 7(6):347-348


1
是的,但是堆也意味着混乱,并且内存堆通常是混乱的。数据结构堆的排序非常好。因此,根据堆的通用定义,同样存在另一种不匹配的情况。
jmucchiello

它总是作为堆栈的反义词引入,足以说明IMO的名称。
reinierpost 2011年

1
这不是巧合-可以通过二项式堆将空闲列表实现为优先级队列。
Heath Hunnicutt

2
@jmucchiello:一堆日志(请参阅图片)井井有条,像树一样。根据我的一本本科教科书,这是数据结构名称的由来。
gioele 2011年

6

实际上,阅读有关内存分配方式的信息(请参阅Buddy Blocks)使我想起了数据结构中的堆。


我对Peter Zhang的回答的评论也与此相关。二进制伙伴系统可以表示为二进制树,并且当每个节点的“键”是其下的内存时,它看起来也像是有效的最大堆(但是这些值是隐式的,并且永不改变)。据我所知,分配算法和释放算法都没有在此二叉树上使用堆操作。
埃里克·杜贝

5

IMO这两个完全无关的事物具有相同的名称只是偶然/巧合。它就像


尽管可以以某种方式关联这两个图。想象一下一个函数的图形,如下所示:元组域,范围是一个顶点,一条边连接两个这样的顶点

2
@Amit:对于连续图,这意味着无限数量的顶点。可以,但是这也使顶点之间的边的概念毫无意义。在函数f(x)= x * 2的图中,在(0,0)和(1,2)之间是否有边?如果是,那么(0,0)和(0.5,1)怎么样?(0,0)和(0.25,0.5)?顶点之间没有边的概念是不可能的,因此这实际上不是图形。
MAK,2009年

5

查找可用内存分配的算法使用类似堆的数据结构。以下摘录自http://www.cprogramming.com/tutorial/virtual_memory_and_heaps.html

new被调用时,它开始寻找适合您的要求尺寸的空闲内存块。假设找到了这样的内存块,则将其标记为保留,并返回指向该位置的指针。有几种算法可以实现此目的,因为必须在扫描整个内存以找到大于对象大小的最小空闲块,或者返回适合内存的第一个空闲块之间做出折衷。为了提高获取内存块的速度,在类似于二进制树(称为堆)的数据结构中保留了内存的可用区和保留区。


1
我对此非常怀疑,特别是“……内存的自由区和保留区以类似于被称为堆的二叉树的数据结构维护”。在我看来,作者正在猜测基于名称“堆”的连接,这可能是错误的。谁能确认/驳斥?
唐·哈奇

1
在对Binary Buddy系统(在Linux中使用)进行了一些深入研究之后,由于它如何划分数据,因此可以用二叉树表示。如果从总内存的角度观察节点,则该二叉树看起来像是一个有效的最大堆,但是没有像在最大堆中那样将节点插入到该二叉树中-节点直接插入到可用内存的最小叶子中> =请求的大小。 1 2 3
埃里克·杜贝

1

在C ++标准中不使用俗语术语“堆栈内存”和“堆内存”。该标准使用静态存储,线程存储,自动存储和动态存储。

可以在“ 存储持久性”部分找到更多信息在标准的“。

因此,从语言和标准库的角度来看,没有混淆。


1

问:什么是堆?A.堆是放置在彼此之上的对象的集合。

回答您的问题:内存堆和二进制堆都使用您所知道的相同概念。数据以堆的形式存储在内存中,其存储顺序与程序中编写的顺序相同。而二进制堆是一种数据结构,其遵循的概念与以堆的形式以有序方式存储数据的概念相同。其他)。让我知道您在评论部分的想法。


-2

也许实现的第一个内存堆是由堆结构管理的?


8
这个假设似乎一点都不明显-堆(数据结构)对于维护堆(动态内存区域)有什么用?
基思·兰德尔2009年

7
-1。我希望有证据的权威性陈述,而不是显而易见的猜测。
罗布·肯尼迪

不大可能。似乎没有充分的理由使用堆(数据结构)来管理堆(可用内存池)。
杰森2009年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.