简体   繁体   English

C ++ A-star实现—确定一个节点是否已经在未清项目的优先级队列中

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

One step in the A* pathfinding algorithm requires searching the list of open nodes for the node you're currently interacting with, and adding that node to the list if it isn't already there, or updating its value and parent, if it's present but with a higher weight than the current version of the node. A *寻路算法的一个步骤要求在打开的节点列表中搜索您当前正在与之交互的节点,如果该节点尚不存在,则将该节点添加到列表中,或者更新该节点的值和父节点(如果存在)但是权重比当前版本的节点高。

These behaviors aren't supported in the STL priority_queue structure. STL priority_queue结构不支持这些行为。 How should I implement that step? 我应该如何执行该步骤?

Updates since this question is getting a lot of views: 由于此问题引起了很多关注,因此进行了更新

  • std::priority_queue may look like a good choice for this, but it isn't. std :: priority_queue看起来可能是个不错的选择,但事实并非如此。

  • Implementing A* yourself is an enormous confidence-booster, but after you've done it, you should try to switch to using the one provided by boost. 自己实现A *可以极大地增强信心,但是在完成之后,您应该尝试改用boost提供的方法。 I was nervous about installing it when I asked this question, but installation is very easy and won't produce any complications; 当我问这个问题时,我对安装它感到不安,但是安装非常简单,不会产生任何麻烦。 and A* isn't the only useful functionality that boost provides. A *不是boost提供的唯一有用的功能。 (In particular, if you don't use their string-processing functionality, you'll end up writing your own copy of it; I speak from personal experience...) (特别是,如果您不使用它们的字符串处理功能,您最终将自己编写它的副本;我的经验是……)

STL priority_queue does not suit for A* implementation. STL priority_queue不适合A *实现。 You need a heap structure that supports the increase operation to change the priority of already inserted items. 您需要支持increase操作的堆结构,以更改已插入项目的优先级。 Use Boost.Heap for an implementation of many classical heaps. 使用Boost.Heap实现许多经典堆的实现。

EDIT: Boost.Graph library has an implementation of A* search too. 编辑: Boost.Graph库也具有A *搜索的实现

If you are limited to STL you could use STL Set and constantly erasing and re-inserting the elements (with new priority). 如果限于STL,则可以使用STL集并不断擦除和重新插入元素(具有新的优先级)。

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) );

Time complexity is still O(log N) but it will probably take more time for large sets. 时间复杂度仍为O(log N),但大型集合可能会花费更多时间。

Here is the solution I used for this if you really want to use std::priority_queue: 如果您真的想使用std :: priority_queue,这是我用于此的解决方案:

When you need to update a node that is already in the priority queue, just insert a new node having the same state and a new cost value and parent into the queue. 当您需要更新优先级队列中已经存在的节点时,只需将状态相同,新的成本值和父节点的新节点插入队列中即可。 The most recently updated copy of this node will come off the queue first and be added to your visited set. 该节点的最新副本将首先从队列中移出,并添加到您的访问集中。 To deal with the older duplicates, check any node coming off the queue against your visited set before processing it. 要处理较旧的重复项,请在处理之前对照访问的集合检查从队列中移出的任何节点。 If it is in the visited set then the lowest-cost path through this node has already been seen, so just ignore it and process the next node. 如果它在访问集中,则已经看到了通过此节点的成本最低的路径,因此只需忽略它并处理下一个节点。

You can use a plain vector or array to store the elements and then use std::make_heap , std::push_heap , std::pop_heap , std::sort_heap , std::is_heap and std::is_heap_until to manage it. 您可以使用简单的向量或数组来存储元素,然后使用std::make_heapstd::push_heapstd::pop_heapstd::sort_heapstd::is_heapstd::is_heap_until进行管理。

This allows you to break containment and implement custom operations on a priority queue, without having to implement the standard operations yourself. 这使您可以打破包含并在优先级队列上实现自定义操作,而不必自己实现标准操作。

There are three likely solutions to this: 有三种可能的解决方案:

  1. Track the list of nodes currently open independently of the priority queue. 跟踪当前打开的节点列表,而与优先级队列无关。 Try creating a list of nodes in the same manner you do for closed nodes. 尝试以与关闭节点相同的方式创建节点列表。

  2. Create a map of nodes (by coordinate) to open-closed state. 创建节点地图(按坐标)到开闭状态。

  3. Install the Boost library, which includes a templated implementation of A* (I think in <graph> ). 安装Boost库,其中包括A *的模板实现(我认为在<graph> )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM