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

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

简而言之:

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

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

更具体地说,我想知道什么是最好的数据结构(可以是一个众所周知的数据结构,或者它们的组合),这样你就不会在算法的任何操作上都有O(n)性能.要求在公开名单上做.

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

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

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

鉴于这些,操作是:

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

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

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

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

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

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

最佳答案 您可以组合哈希表和堆,而不会显示缓慢的操作.

让哈希表映射位置在堆中而不是节点中进行索引.

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

点赞