所有操作都在O(1)中的Minheap是可能的吗?

所有操作都在O(1)中的Minheap是可能的吗?,heap,big-o,graph-algorithm,priority-queue,dijkstra,Heap,Big O,Graph Algorithm,Priority Queue,Dijkstra,Dijkstra算法可用于在O(|V|log(|V|)+E |)中查找图G=(V,E)中从一个节点到任何其他节点的最短路径,其中V表示顶点和E边,以及非负权重函数w 我最近研究了一个具有有限边权重的变体,例如w(n)使用堆,如下所示:创建一个k+1元素的数组(我们称之为map),并记住第一个元素的索引I,以便以后使用(最初为1)。数组的每个元素都应该用一个整数t和一个nil指针初始化,指针现在应该表示双链表的头,其元素计数应该存储在t中。此外,数组中第x个元素中的DLL应准确承载相对于第一个节点

Dijkstra算法可用于在O(|V|log(|V|)+E |)中查找图G=(V,E)中从一个节点到任何其他节点的最短路径,其中V表示顶点和E边,以及非负权重函数w


我最近研究了一个具有有限边权重的变体,例如w(n)使用堆,如下所示:创建一个k+1元素的数组(我们称之为map),并记住第一个元素的索引I,以便以后使用(最初为1)。数组的每个元素都应该用一个整数t和一个nil指针初始化,指针现在应该表示双链表的头,其元素计数应该存储在t中。此外,数组中第x个元素中的DLL应准确承载相对于第一个节点权重为x的节点(即,DLL中的所有元素具有相同的权重,如果我们需要权重相同的节点,则可以互换使用)。比k更远的节点永远不应该存储在任何DLL中(在我们增加第一个数组元素的权重之后,它们仍然可以添加,这将很快看到)

插入到DLL中的每个元素都应获得一个指针,指向其嵌入的DLL中的前置和后置元素。特别是,它应该能够修改其周围的列表

很简单,我们可以在O(1)中从这样的DLL中插入和删除任何元素。由于每个列表的初始索引i是已知的,因此可以在O(1)中访问特定的DLL,因此可以直接访问数组(它需要O(k)操作,这是O(1),因为k是有限的)。迭代所有列表的所有元素是O(n),迭代下一个元素是O(1)

该数组应进一步表示minheap优先级队列H,其根是第一个列表的第一个元素,依此类推

读取H的最小值通常是O(1),因为我们只需读取并删除第一个DLL的第一个元素。但是,此外,我们还要求,如果列表变为空,则应将其删除,并在H的末尾追加一个新的空DLL,其i设置为已删除列表的i加上k+1。这可以很容易地使用某种径向列表来完成。如果列表位于刚刚删除的列表之后,则以相同的方式继续这些列表,直到找到非空列表

减少元素的键在O(1)中也起作用。我们将要reduce的元素与建议的新最小值(这是Dijkstra的一个关键部分)进行比较,如果需要更改,我们将从其DLL中删除该元素(这在O(1)中是可能的,因为该元素确实有指向其pre和post元素的指针),并将其(也在O(1)中)附加到相应的新DLL中

但有待证明的是,地图的大小已经足够了

从初始节点开始,我们通过单个权重小于或等于k的边到达任意数量的其他节点。这些可以简单地插入到初始堆中。通过Dijkstra中的节点迭代,我们总是删除一个初始元素u,它在一开始就有键1。由于其邻域插入到H中,它们最多需要键1+k,这仍然在边界内

一旦以上述方式从H中的第一个DLL中删除了所有元素,我们就会通过在其末尾添加一个新列表(如上所述)来自动增加H。我们继续并将发现,对于任何起始键x,最多可以插入具有新键x+k的元素。因此,映射大小k+1就足够了


因此,堆支持O(1)中所有必需的操作,Dijkstra现在可以在O(|V |+| E |)中执行。

我将在一分钟内添加我自己的证明。这不是更适合这种类型的问题吗?@barakmanos我不确定,这里似乎只存在这个问题的一个标记。如果大多数人同意的话,我会很好的移动。我注意到翻译成英文听起来很尴尬。要考虑为什么你所描述的不是一个最小堆,或者至少有O(log n)来更新min.1)数组中元素的平均数量。2) DLL中的平均元素数?3) 如何确定DLL中的最小值是多少以及这样做的成本是多少?4) 如何确定阵列中的最小值,以及这样做的成本是多少?要点是,您正在查看理想的
log(sqrt(N))(1和3的最佳情况)+log(sqrt(N))(2和4的最佳情况)=log(sqrt(N)*sqrt(N))=log N
@Nuclearman我的答案是:1)数组中正好有k+1个元素,每个元素由int和DLL组成。所有曾经存在的DLL的总和都有| N |个元素。2) 我不知道。我认为这并不重要(见3。)3)DLL中的所有元素都具有相同的优先级,因此我们可以始终插入或删除其任何元素,以获得Dijkstra的有效下一个节点。4) min始终是数组的第一个元素中DLL的任何元素。@Nuclearman我将编辑文本以使这些点更清楚,我认为可能像现在这样难以理解。啊,我现在明白了。那么,你对问题2和问题4的观点是有效的。它们确实是O(1),使用DLL是过度的,堆栈可以很好地完成这项工作。这当然可以改善情况。然而,问题1和问题3仍然存在。在某种意义上,您可以将
k
标记为
O(1)
导致
O(log(1))=O(1)
,但更准确的说法是,它是
O(log(k)),其中(N的最大重量)