Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 从堆的中间删除节点_Algorithm_Data Structures_Heap_Dijkstra - Fatal编程技术网

Algorithm 从堆的中间删除节点

Algorithm 从堆的中间删除节点,algorithm,data-structures,heap,dijkstra,Algorithm,Data Structures,Heap,Dijkstra,从堆的中间删除一个节点可以在O(lgn)中完成,前提是我们可以在固定时间内找到堆中的元素。假设堆的节点包含id作为其字段。现在如果我们提供id,我们如何在O(lgn)时间内删除节点 一种解决方案是,我们可以在每个节点中拥有一个位置的地址,在那里我们维护堆中节点的索引。此数组将按节点ID排序。但这需要维护额外的阵列。有没有其他好方法可以达到同样的效果 PS:我在实现Djikstra的最短路径算法时遇到了这个问题。索引(id、节点)可以在一个哈希表中单独维护,该哈希表具有O(1)查找复杂性(平均)。

从堆的中间删除一个节点可以在O(lgn)中完成,前提是我们可以在固定时间内找到堆中的元素。假设堆的节点包含id作为其字段。现在如果我们提供id,我们如何在O(lgn)时间内删除节点

一种解决方案是,我们可以在每个节点中拥有一个位置的地址,在那里我们维护堆中节点的索引。此数组将按节点ID排序。但这需要维护额外的阵列。有没有其他好方法可以达到同样的效果


PS:我在实现Djikstra的最短路径算法时遇到了这个问题。

索引(id、节点)可以在一个哈希表中单独维护,该哈希表具有O(1)查找复杂性(平均)。然后,总体复杂性仍然是O(logn)。

每个数据结构的设计都考虑了某些操作。来自维基百科关于堆操作

The operations commonly performed with a heap are: create-heap: create an empty heap find-max or find-min: find the maximum item of a max-heap or a minimum item of a min-heap, respectively delete-max or delete-min: removing the root node of a max- or min-heap, respectively increase-key or decrease-key: updating a key within a max- or min-heap, respectively insert: adding a new key to the heap merge joining two heaps to form a valid new heap containing all the elements of both. 通常使用堆执行的操作有: 创建堆:创建一个空堆 查找最大值或查找最小值:分别查找最大堆的最大项或最小堆的最小项 删除最大值或删除最小值:分别删除最大值或最小值堆的根节点 增加密钥或减少密钥:分别在最大或最小堆中更新密钥 插入:向堆添加新密钥 合并合并两个堆以形成包含这两个堆的所有元素的有效新堆。
这意味着,对于您正在寻找的操作,heap不是最佳的数据结构。我建议您寻找更合适的数据结构(取决于您的需求)

我也遇到过类似的问题,下面是我的想法:

解决方案1:如果删除某个随机项的调用将具有指向该项的指针,则可以将单个数据项存储在堆外;让堆成为指向这些项的指针;并使每个项包含其当前堆数组索引

示例:堆包含指向具有键[2 10 5 11 12 6]的项的指针。保存值10的项有一个名为ArrayIndex=1的字段(从0开始计数)。因此,如果我有一个指向第10项的指针,并且想要删除它,我只需查看它的ArrayIndex,然后在堆中使用它进行正常的删除。O(1)查找堆位置,然后通常O(logn)通过递归heapify删除它

解决方案2:如果您只有要删除的项目的关键字段,而不是其地址,请尝试此操作。切换到红黑树,将有效负载数据放入实际的树节点中。这也是用于插入和删除的O(日志n)。它还可以在O(log n)中找到具有给定键的项,这使得delete by key仍然是log n


在这两者之间,解决方案1需要在每次交换时不断更新ArrayIndex字段。它还导致了一种奇怪的一次性数据结构,下一个代码维护人员需要研究和理解这种结构。我认为解决方案2的速度也差不多,而且它的优点是它是一个很好理解的算法。

是的,这是解决方案之一。我认为不使用额外的空间是不可能的。对吗?这种外部hashcode思想的一个问题是,在正常堆中,项总是在Heapify()中移动,这将需要对每个交换进行hashtable更新或delete/insert。这就需要进行大量的哈希表更新,此时,其他一些log-n insert、log-n delete数据结构将更有意义。