A *,打开列表的最佳数据结构是什么?

时间:2016-12-23 07:43:13

标签: data-structures a-star

免责声明:我确实认为这不是类似问题的重复。我已经读过这些,他们(大多数)建议使用堆或优先级队列。我的问题更多的是“我不明白那些在这种情况下会如何起作用”。

简而言之:

我指的是典型的A *(A-star)寻路算法,如维基百科上所述(例如):

https://en.wikipedia.org/wiki/A*_search_algorithm

更具体地说,我想知道什么是最好的数据结构(可以是一个众所周知的数据结构,或者它们的组合),这样你就不会在任何操作上获得O(n)性能该算法需要在打开的列表上执行。

据我所知(主要来自维基百科文章),需要在公开名单上完成的操作如下:

此列表中的元素必须是具有以下属性的Node实例:

  • 位置(或坐标)。为了论证,让我们说这是一个正整数,范围从0到64516(我将我的A *区域大小限制为254x254,这意味着任何一组坐标都可以在16位上进行位编码)< / LI>
  • F得分。这是正浮点值。

鉴于这些,操作是:

  • 将节点添加到打开列表中:如果存在具有相同位置(坐标)的节点(但可能具有不同的F分数),请将其替换。
  • 从打开列表中检索(并删除)具有最低F分数的节点
  • (检查是否存在和)从列表中检索给定位置(坐标)的节点

据我所知,使用堆或优先级队列打开列表的问题是:

  • 这些数据结构将使用F-score作为排序标准
  • 因此,在这种数据结构中添加节点是有问题的:如何最佳地检查具有相似坐标集(但不同的F分数)的节点是否已经存在。此外,即使您以某种方式能够执行此检查,如果您确实找到了这样的节点,但它不在堆/队列的顶部,如何以最佳方式将其删除,以使堆/队列保持正确的顺序
  • 此外,检查存在并根据其位置删除节点不是最佳的,甚至不可能:如果我们使用优先级队列,我们​​必须检查其中的每个节点,如果找到则删除相应的节点。对于堆,如果需要这样的删除,我想所有剩余的元素都需要被提取并重新插入,这样堆仍然是一堆。
  • 这种数据结构良好的唯一剩余操作是当我们想要删除具有最低F分数的节点时。在这种情况下,操作将是O(Log(n))。

此外,如果我们创建一个自定义数据结构,例如使用Hashtable(具有位置作为键)和优先级队列的结构,我们仍然会有一些操作需要对这两者中的任何一个进行次优处理:为了保持它们同步(两者都应该有相同的节点),对于给定的操作,该操作在其中一个数据结构上始终是次优的:按位置添加或删除节点在Hashtable上会很快但在优先级上会很慢队列。删除具有最低F分数的节点将在优先级队列上快速但在Hashtable上缓慢。

我所做的是为使用其位置作为键的节点制作自定义Hashtable,同时跟踪具有最低F分数的当前节点。添加新节点时,会检查其F分数是否低于当前存储的最低F分数节点,如果是,则替换它。当您想要删除节点(无论是按位置还是最低F得分)时,会出现此数据结构的问题。在这种情况下,为了更新持有当前最低F分数节点的字段,我需要遍历所有剩余节点,以便找到现在具有最低F分数的节点。

所以我的问题是:有没有更好的方法存储这些?

1 个答案:

答案 0 :(得分:1)

您可以在不显示慢速操作的情况下组合散列表和堆。

将哈希表映射到堆中的索引而不是节点。

对堆的任何更新都可以自动同步(这需要堆了解哈希表,因此这是侵入性的,而不仅仅是两个现成实现的包装器)到具有更多更新的哈希表(每个O(1),显然)作为在堆中移动的项目数,当然只有log n项可以移动插入,删除最小或更新密钥。哈希表找到节点(在堆中)以更新A *的父更新/ G更改步骤的密钥,这样也很快。