C++ A-star 实现 -- 确定节点是否已在打开项目的优先级队列中

C++ A-star implementation -- determining whether a node is already in the priority queue of open items

本文关键字:项目 优先级 队列 实现 A-star 是否 节点 C++      更新时间:2023-10-16

A* 路径查找算法中的一个步骤需要搜索当前与之交互的节点的开放节点列表,如果该节点尚不存在,则将该节点添加到列表中,或者更新其值和父级(如果它存在但权重高于当前版本的节点)。

STL priority_queue结构不支持这些行为。我应该如何实施该步骤?

由于这个问题获得了很多浏览量,因此进行了更新

  • std::p riority_queue 可能看起来是一个不错的选择,但事实并非如此。

  • 自己实现 A* 是一个巨大的信心助推器,但在你完成之后,你应该尝试切换到使用 boost 提供的助推器。当我问这个问题时,我对安装它感到紧张,但安装非常简单,不会产生任何并发症;A* 并不是 boost 提供的唯一有用功能。(特别是,如果您不使用它们的字符串处理功能,您最终将编写自己的副本;我从个人经验出发...

你可以使用普通向量或数组来存储元素,然后使用std::make_heapstd::push_heapstd::pop_heapstd::sort_heapstd::is_heapstd::is_heap_until来管理它。

这允许您中断遏制并在优先级队列上实施自定义操作,而无需自己实现标准操作。

如果您仅限于 STL,则可以使用 STL Set 并不断擦除和重新插入元素(具有新的优先级)。

Set< pair<int,int> > s; // < priority,value >
s.insert( make_pair(0,5) );
// Decrease Key operation //
s.erase( s.find( make_pair(0,5) ) );
s.insert( make_pair(1,5) );

时间复杂度仍然是O(log N),但对于大型集合可能需要更多时间。

STL priority_queue 不适合 A* 实现。您需要一个支持increase操作的堆结构来更改已插入项目的优先级。使用 Boost.Heap 实现许多经典堆。

编辑:Boost.Graph库也有A *搜索的实现。

如果你

真的想使用 std::p riority_queue,这是我为此使用的解决方案:

当您需要更新已在优先级队列中的节点时,只需将具有相同状态的新节点以及新的成本值和父节点插入队列即可。此节点的最新更新副本将首先从队列中移除,并添加到您访问的集合中。要处理较旧的重复项,请在处理之前根据您访问的集合检查队列中的任何节点。如果它位于访问的集合中,则已经看到了通过此节点的最低成本路径,因此只需忽略它并处理下一个节点即可。

有三种可能的解决方案:

  1. 跟踪当前独立于优先级队列打开的节点列表。尝试以与关闭节点相同的方式创建节点列表。

  2. 创建节点映射(按坐标)到打开-关闭状态。

  3. 安装 Boost 库,其中包括 A* 的模板化实现(我认为在 <graph> 中)。