【问题标题】:How priority queue is used with heap to solve min distance优先级队列如何与堆一起使用来解决最小距离
【发布时间】:2020-08-19 12:48:14
【问题描述】:

请多多包涵,我对数据结构很陌生。

我对如何使用优先级队列来解决最小距离感到困惑。例如,如果我有一个矩阵并且想要找到从源到目标的最小距离,我知道我会执行 Dijkstra 算法,在该算法中,我可以很容易地找到源和矩阵中所有元素之间的距离。

但是,我很困惑这里如何使用堆 + 优先级队列。例如,假设我从网格上的(1,1) 开始,想要找到到(3,3) 的最小距离,我知道如何在查找邻居、检查距离和标记为已访问的意义上实现该算法。但我已经阅读了有关优先队列和最小堆的信息,并希望实现它。

目前,我唯一的理解是优先级队列有一个定位元素的键。我的问题是当我插入第一个邻居(1,0),(0,0),(2,1),(1,2) 时,它们基于一个键(在这种情况下是距离)插入到 pq 中。因此,下一个搜索将是矩阵中距离最短的元素。但是对于 pq,如何在这里使用超过 2 个邻居的堆?例如(1,1) 的孩子就是上面提到的 4 个邻居。这将违反 2*i2*i + 1i/2

总之,我不明白最小堆 + 优先级队列是如何找到距离之类的最小值的。

    0 1 2 3
     _ _ _ _
0 - |2|1|3|2|
1 - |1|3|5|1|
2 - |5|2|1|4|
3 - |2|4|2|1|

【问题讨论】:

  • 确认我已经理解您要解决的问题:您有一个网格,并且您想找到从一个位置到另一个位置的最短路径。每个网格单元是否分配了数字来指示移动到那里的成本?还是更简单的“这里有墙”/“这里没有墙?”
  • @templatetypedef 是的,它们已编号,我会更新它。是的,有界限

标签: java algorithm heap priority-queue dijkstra


【解决方案1】:

您需要使用优先级队列来获得每次移动的最小权重,以便 MinPQ 适合此操作。

MinPQ 使用内部堆技术将元素放在正确的位置操作,例如sink()swim()

所以MinPQ是内部使用堆技术的数据结构

【讨论】:

  • 因此,例如 pq 的长度为 1(源)。然后当我添加 4 个邻居时,他们会使用游泳将它们正确定位在队列中吗?我想我的误解是什么是根节点?这总是源节点吗?
  • 根节点将是树中的最小值
  • 那么在添加后使用swim() 而不是pq.add(node) 更好?
  • MinPQ 外部使用pq.add(node),内部使用swim()
  • 最小值是什么?与源累积的距离?
【解决方案2】:

如果我对您的问题的解释正确,那么您在这一点上就会陷入困境:

但是对于 pq,如何在这里使用一个堆与超过 2 个邻居?例如 (1,1) 的孩子是上面提到的 4 个邻居。这将违背 2*i 和 2*i + 1 和 i/2

听起来让您感到困惑的是,这里有两个独立的概念,您可能会将它们组合在一起。首先,有“网格中的两个地方可能彼此相邻”的概念。在那个世界中,每个位置都有(最多)四个邻居。接下来是二叉堆的形状,其中每个节点都有两个子节点,其位置由数组索引上的某些算术计算给出。它们完全相互独立——二进制堆不知道它存储的项目来自网格,网格也不知道有一个数组,其中每个节点都有两个子节点存储在特定位置。

例如,假设您要将位置 (0, 0)、(2, 0)、(-2, 0) 和 (0, 2) 存储在二进制堆中,并且这些位置的权重为 1 , 2, 3, 和 4,分别。那么二叉堆的形状可能是这样的:

               (0, 0)
              Weight 1
             /        \
          (2, 0)      (0, 2)
         Weight 2    Weight 4
           /
        (0, -2)
       Weight 3

这棵树仍然给每个节点两个孩子;这些孩子不一定映射回网格中节点的相对位置。

更一般地,将优先级队列视为一个黑匣子。想象一下,它只是一个魔法装置,上面写着“你可以给我一些新东西来存储”和“我可以给你迄今为止你给过的最便宜的东西”,仅此而已。事实上,在内部,它恰好被实现为二进制堆,这一事实本质上是无关紧要的。

希望这会有所帮助!

【讨论】:

  • 我正在寻找累积。因此,如果根节点是 1,那么定位到 (2,0 将是 3,定位到 (0,2) 将是 5。但是你能解释为什么 (0,-2) 在它的位置吗?它应该是 root 的右孩子,因为它的距离 4 小于 5。
  • 在我正在处理的示例中,数字 1、2、3 和 4 是累积的权重。请记住,二叉堆的形状将数据组织起来纯粹是为了将低权重的项目保持在顶部,将较重的项目保持在较低的位置,并且那里的父子关系与网格中项目的位置完全无关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-08
  • 2013-11-30
  • 2011-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多