我一直在使用原始开发人员称为heap
的数据结构,它用于实现优先级队列。
虽然有很多关于二叉树的文章,但是(最小/最大)堆似乎不太明确(细节因实现而异)。
我注意到一些特征并不一定适用于二叉树结构。
node
的引用,而不是使用key
来查找节点(这是常见做法)对于二叉树)。对于符合这些特征的数据结构,是否有更详细的术语?或者它只是min/max heap
恰好用作priority-queue
?
注意,这是指具有上述特征的min-heap的链接。
答案 0 :(得分:2)
我认为你混淆了二进制搜索树和二叉树。二叉树更像是一个形状 - 它是一棵树,每个节点最多有两个孩子。节点不一定必须包含值,如果有,则不要求它们遵守任何特定规则。
二进制搜索树是一个二叉树,其中每个节点都有一个密钥,每个节点都遵循以下规则:左子树中的所有密钥都小于节点的密钥,右边的所有密钥都是子树大于节点的密钥。 (一些定义放宽了允许小于或等于而不是小于等的要求。)
还有许多其他数据结构是由二进制树构建的,而不是BST。 k-d树存储多维数据。二进制尝试存储位串。
所以我认为这里最好的描述是“二进制堆是完整的二进制树并遵守堆属性,这与二叉搜索树不同,即使它们具有相同的底层形状(或多或少) 。”
答案 1 :(得分:2)
binary heap是priority queue抽象数据结构的具体实现。它很受欢迎,因为它易于实现,内存效率高且速度相当快:O(log n)插入和O(log n)删除根(最小堆中最小,最大堆中最大)元素。大多数实现还提供了一种peek方法,允许查看根元素而不删除它。
二进制堆没有做任何其他事情。与您的观察相反,在二进制堆中查找特定项目需要顺序扫描。虽然节点是有序的(未排序),但顺序不适合搜索。
二进制堆的典型实现是在数组中。由于形状属性(结构可以被视为完美(或完整)二叉树),这意味着父和子之间的关系是隐式表示的。这些项目以广度优先顺序存储在数组中。
正如用户templatetypedef在他的回答中指出的那样,二进制堆是一种特定的二叉树,不应该与二叉搜索树混淆,二叉搜索树专门用于快速插入和删除项目,以及定位项目按键。
虽然更改堆中项目的优先级或从堆中删除任意项目非常容易,但是您指出的问题是定位要操作的项目。在典型的二进制堆中,查找要修改的项需要顺序搜索。如果您需要能够在堆中移动项目,则通常会将二进制文件与由项目键索引的字典或哈希映射结合在一起。该值是数组中项的索引。每次移动项目时都会更新该索引。这会通过常量因子减慢堆操作,但是您可以在O(1)中找到项目。
还有一种称为Min-max heap的东西,它是一种二进制堆,它允许O(1)访问最小和最大项目。该实现非常类似于标准二进制最小堆的实现。
为了使事情更加混乱,还存在d-ary堆,它是一个堆,每个节点包含两个以上的子节点。例如,三元组每个节点有三个子节点。这些也是在带有隐式子指针的数组中实现的。
还有其他数据结构通常称为堆,但实际上并不真正与堆完全相关,除了它们是优先级队列数据结构的不同实现。最流行的似乎是配对堆,Fibonacci堆和二项式堆,所有这些也可以用二叉树实现。 (同样,不是二叉搜索树。)
几年前,我在博客中写了一篇关于二进制堆(和d-ary堆)的有点引导的介绍。如果您有兴趣,请查看this entry,其中列出了该系列中的所有文章。