So I have a project of which I want to switch to Astar due to speed reasons.
But C++ is not my strongest point. Could anyone help me (or tell me how to do the..) converting the algorythm from Dijkstra to Astar?
I found this Astar implementation:
http://code.google.com/p/a-star-algorithm-implementation/
But I don't know how to use it with my existing code.
Here is the graph file which got the algorithm:
#include "Graph.h"
#include <iostream>
#include <algorithm>
#include <stack>
Graph::Graph(void)
{
}
Graph::~Graph(void)
{
while(!mNodes.empty())
{
delete mNodes.back();
mNodes.pop_back();
}
}
void Graph::addNode(int name, bool exists, Node** NodeID )
{
Node* pStart = NULL;
mNodes.push_back(new Node(name,exists));
std::vector<Node*>::iterator itr;
itr = mNodes.begin()+mNodes.size()-1;
pStart = (*itr);
if(exists == true)pStart->DoesExist_yes();
*NodeID = pStart;
}
void Graph::connect_oneway(Node* pFirst, Node* pSecond, int moveCost)
{
if(pFirst != NULL && pSecond != NULL)
{
pFirst->createEdge(pSecond, moveCost);
}
}
#define MAX_NODES (32768)
#define MAX_CONNECTIONS (5)
#include <time.h>
int * Graph::findPath_r(Node* pStart, Node* pEnd)
{
int *arr = new int[MAX_NODES+2];
for (int i=0; i<MAX_NODES; i++)
arr[i] = -1;
arr[0] = 0;
if(pStart == pEnd)
{
return arr;
}
std::vector<Node*> openList;
openList.push_back(pStart);
Node* pCurrNode = NULL;
while(!openList.empty())
{
//Get best node from open list (lowest F value).
//Since we sort the list at the end of the previous loop we know
//the front node is the best
pCurrNode = openList.front();
//Exit if we're are the goal
if(pCurrNode == pEnd)
break;
//Remove the node from the open list and place it in the closed
openList.erase(openList.begin());
pCurrNode->setClosed(true); //We use a flag instead of a list for speed
//Test all of the edge nodes from the current node
std::vector<Edge*>* pEdges = pCurrNode->getEdges();
Node* pEdgeNode = NULL;
for(std::vector<Edge*>::iterator i = pEdges->begin(); i != pEdges->end(); ++i)
{
pEdgeNode = (*i)->pNode;
//If it's closed we've already analysed it
if(!pEdgeNode->getClosed() && pCurrNode->DoesExist() == true)
{
if(!inList(pEdgeNode,&openList))
{
openList.push_back(pEdgeNode);
pEdgeNode->setGCost(pCurrNode->getGCost()+(*i)->moveCost);
pEdgeNode->calcFCost();
pEdgeNode->setParent(pCurrNode);
}
else
{
//If this is a better node (lower G cost)
if(pEdgeNode->getGCost() > pCurrNode->getGCost()+(*i)->moveCost)
{
pEdgeNode->setGCost(pCurrNode->getGCost()+(*i)->moveCost);
pEdgeNode->calcFCost();
pEdgeNode->setParent(pCurrNode);
}
}
}
}
//Place the lowest F cost item in the open list at the top, so we can
//access it easily next iteration
std::sort(openList.begin(), openList.end(), Graph::compareNodes);
}
//Make sure we actually found a path
if(pEnd->getParent() != NULL)
{
//Output the path
//Use a stack because it is LIFO
std::stack<Node*> path;
while(pCurrNode != NULL)
{
path.push(pCurrNode);
pCurrNode = pCurrNode->getParent();
}
int counter = 0;
arr[1] = 0;
while(!path.empty())
{
arr[counter+2] = path.top()->getName();
counter++;
arr[1] += path.top()->getGCost();
path.pop();
}
arr[0] = counter;
return arr;
}
return arr;
}
bool Graph::inList(Node* pNode, std::vector<Node*>* pList)
{
for(std::vector<Node*>::iterator i = pList->begin(); i != pList->end(); ++i)
{
if((*i) == pNode)
{
return true;
}
}
return false;
}
bool Graph::compareNodes(Node* pFirst, Node* pSecond)
{
return pFirst->getFCost() < pSecond->getFCost();
}
void Graph::reset(void)
{
for(std::vector<Node*>::iterator i = mNodes.begin(); i != mNodes.end(); ++i)
{
(*i)->reset();
}
}
The function for finding the path is this one:
Graph::findPath_r
What I really want to do is preserve the edges (because they decide if the road is both or one-way).
Here are the other files:
Graph.h
#ifndef _GRAPH_H_
#define _GRAPH_H
#include "Node.h"
class Graph
{
public:
Graph(void);
~Graph(void);
//void addNode(int name, bool exists);
void addNode(int name, bool exists, Node** NodeID );
void connect_oneway(int ppFirst, int ppSecond, int moveCost);
void connect_oneway(Node* pFirst, Node* pSecond, int moveCost);
//int * findPath_r(int start, int end);
int * findPath_r(Node* pStart, Node* pEnd);
void reset(void);
private:
void findNodesx(int firstName, Node** ppFirstNode);
bool inList(Node* pNode, std::vector<Node*>* pList);
static bool compareNodes(Node* pFirst, Node* pSecond);
std::vector<Node*> mNodes;
};
#endif
Node.h
#ifndef _NODE_H_
#define _NODE_H_
#include <string>
#include <vector>
//Forward declare Node so Edge can see it
class Node;
struct Edge
{
Edge(Node* node, int cost) : pNode(node), moveCost(cost){}
Node* pNode;
int moveCost;
};
class Node
{
public:
Node(void);
Node(int name, bool exists);
~Node(void);
void createEdge(Node* pTarget, int moveCost);
void setGCost(int cost);
void setClosed(bool closed);
void setParent(Node* pParent);
int getGCost(void);
int getFCost(void);
bool getClosed(void);
Node* getParent(void);
int getName(void);
bool DoesExist(void);
bool DoesExist_yes(void);
std::vector<Edge*>* getEdges(void);
void calcFCost(void);
void reset(void);
private:
int mGCost;
int mTotal;
bool mClosed;
Node* mpParent;
int mName;
bool mHeur;
std::vector<Edge*> mEdges;
};
#endif
Node.cpp
#include "Node.h"
Node::Node(void)
{
}
Node::Node(/*const std::string&*/int name, bool exists) : mGCost(0), mTotal(0), mClosed(false), mpParent(NULL), mName(name), mHeur(exists)
{
}
Node::~Node(void)
{
while(!mEdges.empty())
{
delete mEdges.back();
mEdges.pop_back();
}
}
int Node::getName(void)
{
return mName;
}
void Node::createEdge(Node* pTarget, int moveCost)
{
mEdges.push_back(new Edge(pTarget, moveCost));
}
void Node::setClosed(bool closed)
{
mClosed = closed;
}
bool Node::getClosed(void)
{
return mClosed;
}
std::vector<Edge*>* Node::getEdges(void)
{
return &mEdges;
}
int Node::getGCost(void)
{
return mGCost;
}
void Node::setGCost(int cost)
{
mGCost = cost;
}
void Node::calcFCost(void)
{
mTotal = mGCost;
}
void Node::setParent(Node* pParent)
{
mpParent = pParent;
}
int Node::getFCost(void)
{
return mTotal;
}
bool Node::DoesExist(void)
{
return mHeur;
}
bool Node::DoesExist_yes(void)
{
mHeur = true;
return true;
}
Node* Node::getParent(void)
{
return mpParent;
}
void Node::reset(void)
{
mGCost = 0;
mTotal = 0;
mClosed = false;
mpParent = NULL;
}
You mentioned a library on GoogleCode. It is node clear what you want to do with, and I think the best is to write your implementation yourself.
First, you should know that Dijsktra is a special case of A*. In A*, you have an heuristic, named h; A* = possible implementation of Dijsktra when h is the null function.
Then, about your implementation, let's start with Node. It will need the following functions:
constructor, destructor
create/get edge
set/get parent
set/is closed (for speed)
set/get GCost
set/get FCost
set/is obstacle (name way more descriptive than 'DoesExist')
set/get position
reset
// optional method:
get name
Hopefully, this part of your code won't change a lot. The heuristic code will be placed in the pathfinder. The Edge class is left untouched.
Now the big one: Graph. You won't need to delete any of your public methods.
You will need a heuristic method. For the implementation which will be described, you will need an admissible consistent heuristic:
it must not over-estimate the distance to the goal (admissible)
it must be monotone (consistent)
The general case signature is int getHCost(Node* node);. If you always return 0, you will have a Dijsktra algorithm, which is not what you want. Here we will take the euclidiean distance between the node and the goal. Slower to compute than manhattan distance, but better results. You can change this afterwards.
int getHCost(Node* node, Note* goal);
This implies you must place your nodes in the 3d space. Note that the heuristic is a heuristic, ie, an estimation of the distance.
I won't write the code. I will write some pseudo-code adapted to your situation. The original pseudocode is located on the Wikipedia A* page. This pseudo-code is your findPath_r function:
function A*(start,goal)
set all nodes to not closed // The set of nodes already evaluated.
openset = {start} // The set of tentative nodes to be evaluated, initially containing the start node
start.gcost = 0 // Cost from start along best known path.
// Estimated total cost from start to goal through y.
start.fcost = start.gcost + getHCost(start, goal)
while openset is not empty
current = the node in openset having the lowest f_cost (usually the first if you use a sorted list)
if current == goal
return construct_path(goal)
remove current from openset
current.closed = true
for each neighbor in (node connected by edge in current.edges) // Here is the condition for one-way edges
if neighbor.closed or neighbor.obstacle
continue
gcost = current.gcost + dist_between(current,neighbor) // via edge distance
if neighbor not in openset
add neighbor to openset
neighbor.parent = current
neighbor.gcost = gcost
neighbor.fcost = neighbor.gcost + getHCost(neighbor, goal)
else if gcost < neighbor.gcost
neighbor.parent = current
neighbor.gcost = gcost
neighbor.fcost = neighbor.gcost + getHCost(neighbor, goal)
update neighbor position in openset
return failure
function construct_path(current_node)
std::vector<Node*> path
while current_node != 0
path.push_front(current_node)
current_node = current_node.parent
return path
The implementation above use one-way edges.
You were able to write Dijsktra algorithm in C++, so writing this pseudocode in C++ shouldn't be a problem.
Second part, performances. First, measure ;).
I have some hints that can improve performances:
use a memory pool for allocation deallocation
use an intrusive list for the open list (you can also make it auto-sorted with this technique)
I advise you to read A* for beginners, which is a useful reading, even if you don't use tilemap.
Related
I have a decision tree that includes node and answer that leads us to another nodes. Answers begin with ":" and nodes are the rest.
I have to do a function that delete a subtree from a specific node. For example If I want to delete node "brand?", I want that after that the tree will print from car-color? to blue-is-beautiful
I don't success doing this deletion in the right way because I think I have to delete also the answer red and don't know how to do that.
class Answer
{
public:
string ans;
Node* son;
Answer(string s, Node* p) { ans = s; son = p; }
};
class Node
{
public:
Node(string v) { isLeaf = true; value = v; }
list<Answer*> answersList;
string value;
bool isLeaf;
};
void Tree::del(Node* t)
{
if (t->isLeaf)
return;
for (list<Answer*>::iterator it = t->answersList.begin(); it != t->answersList.end(); it++)
{
del((*it)->son);
delete((*it));
*it = NULL;
}
if (t)
{
delete t;
t = NULL;
}
}
Now having understood the problems (highly restrictive requirements and what is causing your code to fail), I now have an answer for you.
The issue is, that you need to remove the node you've deleted from the collection it is stored in.
For this purpose, you need to use an alternate version of your search to detect, which child has the value you are looking for.
Due to the requirement of 'not adding any additional functions', there are two ways to go about this.
One is to employ recursion using an anonymous function, the other is 'check the child prior to diving into it'.
The following code fragment uses a DIY-Lambda-Functor, which employs the recursion method.
void Tree::deletefromNode(string val)
{
bool didFindValue = false;
std::function<bool (Node *, const string &)> functor;
class Functor
{
public:
Functor(Tree *owner, bool &didFindValue) : owner(owner), didFindValue(didFindValue)
{
}
bool deleteFromNode(Node *node, const string &value)
{
bool foundMatch = false;
if (node)
{
foundMatch = (node->value == value);
if (!foundMatch)
{
for (list<Answer*>::iterator it = node->answersList.begin(); it != node->answersList.end();)
{
Node *childNode = (*it)->son;
if (deleteFromNode(childNode, value))
{
owner->del(childNode);
it = node->answersList.erase(it);
didFindValue = true;
}
else
it++;
}
}
}
return foundMatch;
}
private:
Tree *owner;
bool &didFindValue;
};
Functor(this, didFindValue).deleteFromNode(root, val);
if (didFindValue)
cout << "Value not found" << endl;
}
I keep running through the program and changing around pointers and I don't see what I am missing. I keep getting a read access violation on line 42 of the .cpp file and I am genuinely confused on how.
Here is the .cpp file
#include "Graph.h";
void Graph::insertEdge(int from, int to, int weight)
{
if (from <= size && to <= size)
{
bool leave = true;
EdgeNode* current = vertices[from].edgeHead;
while (leave)
{
if (from == current->adjVertex || current == nullptr) //Read access violation here
{
current->weight = weight;
if (current == nullptr)
{
current->adjVertex = to;
current->nextEdge = nullptr;
}
leave = false;
}
else
current = current->nextEdge;
}
}
}
and here is the .h file
#include "Vertex.h";
#include <fstream>;
using namespace std;
class Graph
{
static const int MAX_VERTICES = 101;
struct EdgeNode
{
int adjVertex = 0;
int weight = 0;
EdgeNode* nextEdge = nullptr;
};
struct VertexNode
{
EdgeNode* edgeHead = nullptr;
Vertex* data = nullptr;
};
struct Table
{
bool visited;
int dist;
int path;
};
public:
void buildGraph(ifstream& in);
void insertEdge(int from, int to, int weight);
void removeEdge(int beginning, int end);
void findShortestPath();
void displayAll();
void display(int begin, int end);
private:
int size;
VertexNode vertices[MAX_VERTICES];
Table T[MAX_VERTICES][MAX_VERTICES];
};
I've been on this problem for multiple hours now and I can't seem to find the issue.
Probably instead of
if (from == current->adjVertex || current == nullptr)
you should first ensure the pointer is not null before dereferencing it.
if (current == nullptr || from == current->adjVertex)
then if current is null, the right-hand side of || operator won't be run.
HOWEVER, you will still have a problem because you also dereference current->weight inside the if-statement, even if current is null.
Following code is about searching for neighbours in realtime. As soon as a new node is added to my graph, the function updateSeqNeighbours for this node is called. What I know is, that the new node is definitely neighbour to the last one added. In the next step I use this fact to look in the neighbourhood of the previously added node, find the one closest to the new and then search this neighbourhood for the closest neighbour.
I repeat this only for example 3 times, to limit the number of neighbours for one node to 4 to keep a constant time frame for calculation. It works wonderful, except for after ~30 nodes the calculation time increases very fast with every additional node resulting in a bad_alloc exception.
#ifndef GRAPH_NODE_H_
#define GRAPH_NODE_H_
#include <vector>
#include <cmath>
#include <iostream>
using namespace std;
class Node {
public:
double x;
double y;
Node* nodePrev;
vector<Node> seqNeighbours;
//Constructor
Node();
Node(double x, double y);
virtual ~Node();
//Operator functions
Node& operator=(const Node& n);
//Get&Set
int getID();
//Public member functions
void addNeighbour(Node& n);
bool isSeqNeighbour(int ID);
int updateSeqNeighbours();
double distanceTo(Node& n);
private:
static int count;
int ID;
void _setDefaults();
};
int Node::count = 0;
Node::Node() {
_setDefaults();
}
Node::Node(double x, double y) {
_setDefaults();
this->x = x;
this->y = y;
}
Node::~Node() {
// TODO Auto-generated destructor stub
}
//Operator functions
Node& Node::operator=(const Node& n) {
if (this != &n) {
ID = n.ID;
x = n.x;
y = n.y;
seqNeighbours.clear();
seqNeighbours = n.seqNeighbours;
nodePrev = n.nodePrev;
}
return *this;
}
//Get&Set
int Node::getID() {
return this->ID;
}
//Public member functions
void Node::addNeighbour(Node& n) {
seqNeighbours.push_back(n);
}
double Node::distanceTo(Node& n) {
return sqrt((n.x-x)*(n.x-x) + (n.y-y)*(n.y-y));
}
bool Node::isSeqNeighbour(int ID) {
for (int i = 0; i < seqNeighbours.size(); i++) {
if (seqNeighbours[i].getID() == ID) {
return true;
}
}
return false;
}
int Node::updateSeqNeighbours() {
if (nodePrev == NULL) {
return 1;
} else {
Node seed = *nodePrev; //previous node as seed
seqNeighbours.push_back(seed);
for (int i = 0; i < 3; i++) {
if (seed.nodePrev == NULL) break;
double minDist = 15353453;
Node closest;
for (int j = 0; j < seed.seqNeighbours.size(); j++) {
double dist = distanceTo(seed.seqNeighbours[j]);
if (dist < minDist) {
minDist = dist;
closest = seed.seqNeighbours[j];
}
}
if (minDist < 150) {
seqNeighbours.push_back(closest);
}
seed = closest;
}
cout << "neighbours = " << seqNeighbours.size() << endl;
}
return 0;
}
void Node::_setDefaults() {
x = 0;
y = 0;
ID = count;
nodePrev = NULL;
seqNeighbours.clear();
count++;
}
#endif /* GRAPH_NODE_H_ */
Graph:
#ifndef GRAPH_GRAPH_H_
#define GRAPH_GRAPH_H_
#include <vector>
#include <iostream>
#include "Node.h"
using namespace std;
class Graph {
public:
Graph();
virtual ~Graph();
vector<Node> list;
void addNode(Node& n);
void addSeqNode(Node& n);
private:
void _setDefaults();
};
Graph::Graph() {
// TODO Auto-generated constructor stub
}
Graph::~Graph() {
// TODO Auto-generated destructor stub
}
void Graph::addNode(Node& n) {
list.push_back(n);
}
void Graph::addSeqNode(Node& n) {
if (!list.empty()) {
n.nodePrev = &list.back();
}
n.updateSeqNeighbours();
list.push_back(n);
}
void Graph::_setDefaults() {
list.clear();
}
#endif /* GRAPH_GRAPH_H_ */
I suspect running out of memory causes this. However 40 nodes with each 4 neighbours doesn't sound much of a problem to me. Anyone any idea what goes wrong?
Edit:
Error in german, so I need to guess:
An exception accured in project prSimulation1.exe of class std::bad_alloc. Adress of Exception: '0x5476016'. Process was stopped.
Your seqNeighbours is vector<Node>. That means it stores the neighbours themselves, not pointers to them or their indices. The copy constructor, therefore, copies all the neighbours. Copying each neighbour, in turn, requires to copy its neighbours, which requires to copy their neighbours, and so on. Your assignment also copies all the neighbours, which requires to copy their neighbours, and so on. This means that each copy exponentially increases memory load, until the system is unable to store all the neighbours, neighbours of neigbours etc.
PS: on a side note, a vector called "list" is a bad idea. It is like a list called "vector", a set called "map", or a cat called Dog.
I am trying to make a generic Segment Tree Class for updates and range queries.
Instead of assuming that the elements would just be integers and the operation to be done over a range of elements would be their sum or product, i would want the user to provide the type T of the element and a function, which i named compose.
This function takes in two parameters of type T and returns a value of the same type T. This return value is the result when that desired operation is performed over range of 2 elements which i can use to perform that same operation on a range of any number of elements.
The class is as follows:
#include <functional>
template<class T>
class SegmentTree {
public:
class binary_function_unitype: public std::binary_function<T,T,T> {
public:
virtual T operator() (T arg1, T arg2) {};
};
private:
class Node {
public:
T value;
int seg_start, seg_end;
Node* left;
Node* right;
Node (T value, int seg_start, int seg_end, Node* left=0, Node* right=0) {
this->value = value;
this->seg_start = seg_start;
this->seg_end = seg_end;
this->left = left;
this->right = right;
}
};
// Not expecting the compose function to be robust enough.
T composeUtil (T arg1, T arg2) {
if (arg1!=0 && arg2!=0)
return compose(arg1,arg2);
else if (arg1!=0)
return arg1;
else if (arg2!=0)
return arg2;
}
// Creating the Segment Tree.
Node* createTree (T leaves[], int start, int end) {
// base case - leaf of tree.
if (start==end)
return new Node(leaves[start],start,start,0,0);
// general case.
int mid = start + (end-start)/2;
Node* left = createTree(leaves,start,mid);
Node* right = createTree(leaves,mid+1,end);
T retValue = composeUtil(left->value,right->value);
return new Node(retValue,start,end,left,right);
}
// Range Query helper.
T queryUtil (Node* root, int start, int end) {
int seg_start = root->seg_start, seg_end = root->seg_end;
if (seg_start>end || seg_end<start)
return 0;
else if (seg_start>=start && seg_end<=end)
return root->value;
else
return compose( queryUtil(root->left,start,end), queryUtil(root->right,start,end));
}
// Helper function for Updating the Segment Tree.
void updateUtil (Node* root, int position, T updatedValue) {
int seg_start = root->seg_start, seg_end = root->seg_end;
if(seg_start>position || seg_end<position)
return;
else if(seg_start==seg_end)
root->value = updatedValue;
else
root->value = composeUtil(root->left->value,root->right->value);
}
// Freeing the memory allocated to the Segment Tree.
void destroyTree(Node* root) {
if (root->left!=0)
destroyTree(root->left);
if (root->right!=0)
destroyTree(root->right);
delete root;
}
Node* root;
binary_function_unitype compose;
public:
SegmentTree (T leaves[], binary_function_unitype compose, int start, int end) {
this->compose = compose;
this->root = createTree(leaves, start, end);
}
T query (int start, int end) {
return queryUtil(root, start, end);
}
void update (int position, T updatedValue) {
updateUtil(root, position, updatedValue);
}
~SegmentTree () {
destroyTree(root);
}
};
When I tried to use this class, it turns out that the compose function, which I took in as a paramater is not being used, on the contrary the one from the class binary_function_unitype is being used.
I expected that the function definition from the user would override the one in class binary_function_unitype and my work would be done. But that did not happen. The program using this class is as follows:
#include <iostream>
#include "SegmentTree.h"
using namespace std;
class Compose: public SegmentTree<int>::binary_function_unitype {
public:
int operator() (int arg1, int arg2) {
return arg1+arg2;
}
};
int main()
{
int num;
cin>>num;
int arr[num];
for(int i=0;i<num;i++)
cin>>arr[i];
Compose compose;
SegmentTree<int> segTree(arr, compose, 0, num-1);
int s,e;
cin>>s>>e;
cout<<segTree.query(s-1,e-1);
return 0;
}
Can somebody tell me whats the flaw in my approach or if I misunderstood some basic concept about using inheritance or templates in C++ ?
Thanks.
The constructor takes a binary_function_unitype by value, so it will slice.
I've a question to ask.
So, I have a structure call Node as shown below:
struct Node
{
int xKoor, yKoor;
Node *parent;
char nodeId;
float G;
float H;
float F;
Node(int x, int y, int id, Node * par)
{
xKoor = x;
yKoor = y;
nodeId = id;
parent = 0;
}
Node(int x, int y, char id)
{
xKoor = x;
yKoor = y;
nodeId = id;
}
};
And I have list that contains elements of this structure:
list<Node*> OPEN;
This list's size varies in time.
What I need to do is to find the Node object which has the minimum F value, then pop out that object from the list.
So, I tried to write a function as shown below:
void enKucukFliNodeBul(list<Node*> OPEN)
{
list<Node*>::iterator it = OPEN.begin();
for(it = OPEN.begin(); it != OPEN.end(); it++)
{
if(it._Ptr->_Myval->F < it._Ptr->_Next->_Myval->F)
{
}
}
}
But I'm stuck. I'm new to STL. How can I solve this?
My best regards...
You can use std::min_element with a suitable comparison function for this.
bool nodeComp(const Node* lhs, const Node* rhs) {
return lhs->F < rhs->F;
}
#include <algorithm> // for std::min_element
list<Node*>::iterator it = std::min_element(OPEN.begin(), OPEN.end(), nodeComp);
This assumes that list<Node*> is std::list<Node*>, in which case you should be aware that std::list itself is a linked list.
Other useful operations, based on your comments:
Remove a minimum value node from the list and delete it:
OPEN.erase(it);
delete *it; //
You may need to perform other operations, if your nodes depend on each other.
Sort the list:
OPEN.sort(nodeComp);
use std::min_element algirithm and overload Compare function
bool compareF(Node *lhs, Node *rhs)
{
return lhs->F < rhs->F;
}
if you are using C++03:
std::<Node*>::itertor ter = std::min_element(OPEN.begin(),OPEN.end(), compareF);
if you are using C++11:
auto iter = std::min_element(OPEN.begin(),OPEN.end(), compareF);
To sort the list, you can call OPEN.sort(compareF); to sort your list with compareF function
Try adding this:
bool compare_node_F(Node* n1, Node* n2)
{
return n1-> F< n2-> F;
}
#include <list>
#include <algorithm>
#include <cstdlib>
#include <iostream>
int main()
{
std::list<Node*> nodes;
for(int i= 100; i--;)
{
Node* n= new Node(42, 42, 42);
n-> F= i;
nodes.push_back(n);
}
std::list<Node*>::iterator min_element_iter= std::min_element(nodes.begin(), nodes.end(), compare_node_F);
std::cout<< "Min F: "<< (*min_element_iter)-> F<< '\n';
for(std::list<Node*>::iterator d= nodes.begin(); d!= nodes.end(); ++ d)
delete *d;
}