简体   繁体   中英

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.

These behaviors aren't supported in the STL priority_queue structure. 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.

  • 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. 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. (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. You need a heap structure that supports the increase operation to change the priority of already inserted items. Use Boost.Heap for an implementation of many classical heaps.

EDIT: Boost.Graph library has an implementation of A* search too.

If you are limited to STL you could use STL Set and constantly erasing and re-inserting the elements (with new priority).

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.

Here is the solution I used for this if you really want to use 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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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