【问题标题】:Why are two different concepts both called "heap"? [duplicate]为什么两个不同的概念都称为“堆”? [复制]
【发布时间】:2010-12-14 12:26:39
【问题描述】:

为什么 C 风格语言和the data structure 都将运行时堆用于动态内存分配?有关系吗?

【问题讨论】:

标签: c++ heap terminology heap-memory


【解决方案1】:

Donald Knuth 说(计算机编程的艺术,第三版,第 1 卷,第 435 页):

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

他没有说是哪位作者,也没有给出任何具体论文的参考,但确实说“堆”这个词与优先级队列的关系是这个词的传统含义。

【讨论】:

  • 池会比堆更好。
  • 有趣。有人应该问他是否记得哪些作者。
  • 维基百科声称这是因为早期 Lisp 使用堆(数据结构)来实现其内存存储。它没有说如何。它的参考文献是“Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest (1990): Introduction to algorithm. MIT Press / McGraw-Hill.”,我没有。
  • 我对此没有参考,但我的猜测是,最初用于组织对打开的内存块的引用的数据结构是一个最小堆。似乎这至少是一种快速找到最小内存块的好方法,可以让您存储您尝试存储的数据更新:我所说的听起来完全像好友块en.wikipedia.org/wiki/Dynamic_memory_allocation#Buddy%5Fblocks
  • @SteveJessop - 检查 Cormen、Leiserson、Rivest、Stein - 第 3 版(2009 年)在 Heapsort 章节的开头,它只说““堆”一词最初是在 heapsort 的上下文中创造的,但是此后,它开始指代“垃圾收集存储”,例如 Java 和 Lisp 提供的编程语言。我们的堆数据结构不是垃圾收集存储,本书中提到堆时,我们指的是一种数据结构,而不是垃圾收集的一个方面。 CLRS - 第二版也有几乎完全相同的措辞(没有迹象表明 Lisp 使用了堆)。
【解决方案2】:

它们具有相同的名称,但实际上并不相似(甚至在概念上)。内存堆被称为堆,就像您将洗衣篮称为“衣服堆”一样。该名称用于表示可以随意分配和释放内存的有些杂乱的地方。数据结构(正如您引用的维基百科链接所指出的)完全不同。

【讨论】:

  • 是的,我认为这正是他提出问题的重点:它们是不同的。那么为什么它们被称为同一个东西 - 是否有一些潜在的关系。
  • 我解释这个答案的方式是“不,没有潜在的关系”,所以它回答了这个问题。
  • 安德鲁正在回答这个问题。没有关系。只是巧合。内存堆更符合常见用法,因为内存的分配就像“衣服堆”一样。然而,数据结构需要更大的想象力。这变成了一个更有趣的“为什么”。该名称来自事实节点按其键排列,并且父节点键始终 >= 大于其子节点。
  • 它们绝对是无关的。然而,将其称为“堆”的问题在于“堆的”对应物——“堆栈”——也是一个实际的堆栈。
  • 我知道为什么堆数据结构被称为堆:因为它满足堆属性。但是为什么堆属性这样称呼呢?这对我来说毫无意义,因为像“头重脚轻”这样的名字会更好。
【解决方案3】:

名字冲突是不幸的,但并不是那么神秘。 是一个小而常见的词,用于表示堆、集合、组等。该词用于数据结构早于(我很确定)池的名称的记忆。事实上,在我看来,pool 会是后者更好的选择。 表示垂直结构(像一堆),它适合数据结构,但不适合内存池。我们不认为内存池堆是分层的,而数据结构背后的基本思想是将最大的元素保持在堆(和子堆)的顶部。

堆数据结构可以追溯到60年代中期;堆内存池,70年代初。至少早在 1971 年,Wijngaarden 在讨论 Algol 时就使用了术语堆(意思是内存池)。

作为数据结构最早的使用可能是七年前的
Williams, J. W. J. 1964。“算法 232 - Heapsort”,ACM 通信 7(6): 347-348

【讨论】:

  • 是的,但是堆也意味着无序,内存堆通常是无序的。数据结构堆是非常有序的。因此,根据堆的通用定义,同样会出现同样的不匹配。
  • 它总是作为 stack 的反义词引入,这足以解释 IMO 的名称。
  • 这不是巧合——空闲列表可以通过二项式堆实现为优先级队列。
  • @jmucchiello:一堆日志(请参阅picture)有序且类似于树。根据我的一本本科教科书,这是数据结构名称的由来。
【解决方案4】:

实际上,阅读内存分配方式(参见Buddy Blocks)让我想起了数据结构中的堆。

【讨论】:

  • 我对张彼得的回答的评论也与此处相关。二元伙伴系统可以表示为二叉树,当每个节点的“键”是它下面的 total 内存时,它也看起来像一个有效的最大堆(但这些值是隐含的,并且从不改变)。据我所知,分配和释放算法都没有在这棵二叉树上使用堆操作。
【解决方案5】:

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

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

【讨论】:

  • 我对此非常怀疑,特别是“......内存的空闲和保留区域被维护在一个类似于二叉树的数据结构中,称为堆。”在我看来,作者根据“堆”这个名称猜测存在联系,并且可能是错误的。任何人都可以确认/反驳吗?
  • 在对 Binary Buddy 系统(在 Linux 中使用)进行了一些简单的研究之后,由于它对数据的分区方式,它可以用二叉树表示。如果您根据总内存观察节点,这个二叉树看起来像一个有效的最大堆,但是节点不会像它们在最大堆中那样插入到这个二叉树中 - 节点直接插入到可用内存的最小叶中 > = 请求的大小。 123
【解决方案6】:

IMO 这两个完全不相关的事物具有相同的名称只是一个意外/巧合。就像graphgraph

【讨论】:

  • 这两个图虽然可以以某种方式相关。想象一个函数的图如下:元组域,范围)是一个顶点,一条边连接两个这样的顶点
  • @Amit:对于意味着无限数量的顶点的连续图。这没关系,但这也使顶点之间的边的概念变得毫无意义。在函数 f(x)=x*2 的图中,(0,0) 和 (1,2) 之间是否存在边?如果是,那么(0,0)和(0.5,1)怎么样? (0,0)和(0.25,0.5)?顶点之间没有边的概念,所以这不是真正的图。
【解决方案7】:

C++ 标准中不使用俗称的堆栈内存和堆内存。该标准使用静态存储、线程存储、自动存储和动态存储。

更多内容请参见标准的Storage Duraction section

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

【讨论】:

    【解决方案8】:

    问。什么是堆? A. 堆是相互重叠的对象的集合。

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

    【讨论】:

    • 内存堆和二叉堆使用的概念如你所知。内存堆和堆数据结构没有任何共同点
    【解决方案9】:

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

    【讨论】:

    • 这个假设似乎并不明显——堆(数据结构)对于维护堆(动态内存区域)有什么用处?
    • -1。我更喜欢有证据的权威声明,而不是显然只是猜测。
    • 极不可能。似乎没有充分的理由使用堆(数据结构)来管理堆(空闲内存池)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多