- algorithm/
- Algorithm 是否有一个堆或类似堆的结构可以与指针一起工作,换句话说,节点不在数组中?
Algorithm 是否有一个堆或类似堆的结构可以与指针一起工作,换句话说,节点不在数组中?
Algorithm 是否有一个堆或类似堆的结构可以与指针一起工作,换句话说,节点不在数组中?,algorithm,heap,doubly-linked-list,Algorithm,Heap,Doubly Linked List,我现在有一个按降序排列的对象的双链接列表。(列表是侵入性的——对象中的指针。)我有一组非常有限的操作:
添加具有最高可能密钥的节点
删除具有最高可能密钥的节点(不管是哪一个)
删除键为0的节点(无论是哪一个)
具有最高当前密钥的节点的增量密钥(无论是哪一个)
键大于0的任何给定节点的减量键
操作1-4将是恒定时间,但操作5是O(n),其中n=具有相同键值的节点数。这是因为这些节点在递增时,必须移动到具有相同键值的同级节点之后,并放置在该范围之后。并且发现重新插入的位置将是O(n)
我认为heap
我现在有一个按降序排列的对象的双链接列表。(列表是侵入性的——对象中的指针。)我有一组非常有限的操作:
添加具有最高可能密钥的节点
删除具有最高可能密钥的节点(不管是哪一个)
删除键为0的节点(无论是哪一个)
具有最高当前密钥的节点的增量密钥(无论是哪一个)
键大于0的任何给定节点的减量键
操作1-4将是恒定时间,但操作5是O(n),其中n=具有相同键值的节点数。这是因为这些节点在递增时,必须移动到具有相同键值的同级节点之后,并放置在该范围之后。并且发现重新插入的位置将是O(n)
我认为heap(heapsort heap,而不是malloc heap)是一种解决方案,其中最坏的情况是O(logn)(其中n=节点数)。然而,根据我的回忆和谷歌的发现,它似乎总是以数组的形式实现,而不是以二叉树的形式实现。因此:
问题:是否有一种堆实现以二叉树的方式使用指针,而不是数组的方式,来维护典型数组实现的O()?一种常见的方法是使用基于数组的堆,但是:
- 在堆中存储指向节点的指针李>
- 在每个节点中,将其索引存储在堆中;及
- 无论何时交换堆中的元素,都会更新相应节点中的索引李>
这保留了所有堆操作的复杂性,每个节点大约需要1.5个指针和1个整数。(额外的.5是因为可扩展阵列的实现方式)
或者,您可以将节点链接到一个带有指针的树中。但是,为了支持所需的操作,每个节点需要3个指针(父节点、左节点、右节点)
这两种方法都可以很好地工作,但是阵列实现更简单、更快,并且使用的内存更少
预计到达时间:
不过,我应该指出,如果使用指针,那么可以使用不同类型的堆。斐波那契堆将允许您在摊余常数时间内减少节点的值。不过,这有点复杂,而且在实践中很慢:不幸的是,书面问题的答案并不是书面问题标题的答案
解决方案1:摊销O(1)数据结构
找到了一个解决方案,其中包括所有必需操作的摊销O(1)实现
它只是一个双链表的双链表。“主”双链接列表节点称为父节点,每个键值最多有一个父节点。父节点保留具有相同键值的子节点的双链接列表。每个子级还指向其父级
添加具有最高可能值的节点:如果没有列表头或其值不是最大值,请将新节点添加到主链接列表头。否则,将其添加到头部节点的子列表的尾部
删除可能具有最高值的(任何)节点:如果有多个具有最高值的项目,则删除哪一个并不重要。因此,如果头部父项有子项,则从子项列表中删除尾部子项。否则,请从主列表中删除父级
删除值为0的(任意)节点:相同的操作
当前值最高的(任意)节点的增量值:如果多个节点具有相同的键值,我们可以选择任意一个,因此选择头部父节点的尾部子节点。将其从子列表中删除。如果增加它的值超过了最大值,那么就完成了。否则它就是一个新的头部节点。如果没有子级,则在适当的位置增加头部父级,如果超过最大值,则将其移除
任何大于0的节点的递减值:如果该节点是子节点,请从子列表中删除,然后添加到父节点的后续子列表或作为父节点之后的新节点。没有子项的父项:如果主列表中的后续项仍然具有较小的键,则完成。否则,将其删除并添加为继任者的尾部子项。有孩子的父母:相同,但要让领班的孩子代替这是O(n),其中n=给定大小的节点数,因为必须更改所有子节点的父指针。但是,如果选择递减的节点作为给定大小的所有节点的父节点的几率为1/n,则摊销为O(1)
主要的缺点是逻辑上每个节点有7个不同的指针。如果是父角色,我们需要上一个和下一个父角色,以及头和尾子角色。如果是子角色,我们需要上一个和下一个子角色,以及父角色。这些指针可以合并为4和3指针的两个交替子结构,这样可以节省存储空间,但不会节省CPU时间(可能需要将未使用的指针归零以保持清洁)。更新它们不会很快
解决方案2:草率就足够了
另一种方法就是草率行事。该应用程序从查找分数较高的节点中获益,但它们绝对处于完美的顺序并不重要。因此,我们可以接受一种解决方案,而不是通过O(n)操作将节点从链的一端潜在地移动到另一端,这种解决方案可以执行O(1)操作,尽管有时并不完美
这可能是目前实施的一种双重链接列表。它可以支持除O(1)中的减量以外的所有操作。它可以处理O(1)中唯一键值的递减。只有非唯一键值的递减才会变为O(n),因为我们需要跳过具有上一个键值的剩余节点,以找到具有相同或hi的第一个节点