【问题标题】:A*, what's the best data structure for the open list?A*,开放列表的最佳数据结构是什么?
【发布时间】:2017-05-08 21:51:51
【问题描述】:

免责声明:我真的相信这不是类似问题的重复。我读过这些,他们(大部分)建议使用堆或优先级队列。我的问题更多的是“我不明白这些在这种情况下如何工作”。

简而言之:

我指的是典型的 A*(A 星)寻路算法,如 Wikipedia 上所述(例如):

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

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

据我了解(大部分来自维基百科的文章),对open list需要做的操作如下:

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

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

鉴于这些,操作是:

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

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

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

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

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

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

【问题讨论】:

    标签: data-structures a-star


    【解决方案1】:

    您可以将哈希表和堆结合起来,而不会出现缓慢的操作。

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

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

    【讨论】:

    • 这听起来很有希望。我的问题是:当通过节点坐标(不是最低 F 的节点)删除节点时,我应该做的是:使用 hashmap 在堆中(在其支持数组中)找到该节点的索引。从哈希图中删除节点条目。但是,我该如何从堆中删除它?我应该从支持堆的数组中拼接那个位置吗?那不会破坏堆吗?我应该从该节点的位置开始缩小堆并朝向堆的后备数组的末尾吗?
    • @ShivanDragon 与 remove-min 类似的处理,窃取堆中的最后一项,将其放入“洞”中,然后将其向下移动以恢复堆属性
    • 谢谢,现在我明白你回答的方方面面了。
    猜你喜欢
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 1970-01-01
    • 2019-11-21
    • 1970-01-01
    • 2011-10-23
    • 2018-07-17
    • 2011-05-15
    相关资源
    最近更新 更多