I'm working on an assignment and the goal is to make a module that will assist in representing a priority queue displaying each 'item' and it's appropriate 'priority value'. I'm not asking anybody to do my "homework" for me as stated in my previous post, I'm simply asking for help understanding where I am going wrong with my insert and insertCell functions that gives me errors. Any advice/tips would be very helpful in solving my problem.
//Beginning of Code
//File: pqueue.cpp
//Module pqueue.cpp provides priority queues that include items and their
//priority types. It tests for empty queues, can insert priority queues that
//include a new item with a new priority, can remove priority queues and/or
//items with their priorities, and can print each item along with its priority
//to the standard output.
//
//
#include <cstdio>
#include "pqueue.h"
#include <cstdlib>
using namespace std;
//An object of type PQCell represents a cell in a linked list.
//
//PQCell has three field.
//
//item- the particular item that is entered
//priority- the priority that an item has
//nextList- a pointer to the next cell in the list
struct PQCell
{
ItemType item;
PriorityType priority;
PQCell *nextItem;
PQCell(ItemType a, PriorityType b, PQCell* nextCell)
{
item = a;
priority = b;
nextItem = nextCell;
}
};
//Function isEmpty returns true if the queue is empty and false if it is not.
bool isEmpty(const PriorityQueue& q)
{
if(q.cells == NULL)
{
return false;
}
return true;
}
//Function insertCell inserts item x with priority p into a linked list 'L'.
void insertCell(PQCell*& L, ItemType x, PriorityType p)
{
if(L==NULL || L -> priority > p)
{
L = new PQCell(x, p, L);
}
else
{
insertCell(L -> nextItem, x,p);
}
}
//Function insert inserts item x with priority p into a priority queue 'q'.
void insert(PriorityQueue& q, ItemType x, PriorityType p)
{
insertCell(q, x, p);
}
//Function printPriorityQueue prints a representation of the priority queue
//including each value, x, and it's priority type, y, respectively.
void printPriorityQueue(const PriorityQueue& q, ItemPrinter printItem,
PriorityPrinter printPriority)
{
PQCell* pointer = q.cells;
while(pointer != NULL)
{
printf("Item = ");
(printItem)(pointer->item);
printf(" Priority = ");
(printPriority)(pointer->priority);
printf("\n");
pointer = pointer -> nextItem;
}
}
//Function remove removes the item with the smallest priority. It also stores
//the item and it's priority into x and p, respectively.
void remove(PriorityQueue& q, ItemType& x, PriorityType& p)
{
if(q.cells != NULL)
{
PQCell *pointer = q.cells;
q.cells = q.cells -> nextItem;
x = pointer -> item;
p = pointer -> priority;
delete [] pointer;
}
else
{
printf("Q is empty");
exit(1);
}
}
//File: pqueue.h
typedef const char* ItemType;
typedef double PriorityType;
struct PQCell;
typedef void (*ItemPrinter)(ItemType);
typedef void (*PriorityPrinter)(PriorityType);
struct PriorityQueue
{
PQCell* cells;
PriorityQueue()
{
cells = NULL;
}
};
bool isEmpty(const PriorityQueue& q);
void insert(PriorityQueue& q, ItemType x, PriorityType p);
void printPriorityQueue(const PriorityQueue& q, ItemPrinter printItem,
PriorityPrinter printPriority);
void remove(PriorityQueue& q, ItemType& x, PriorityType& p);
The main problem I'm having is like I said, the insert and insertCell functions. I keep receiving the errors:
pqueue.cpp: In function void insert(PriorityQueue*&, ItemType, PriorityType):
pqueue.cpp:70:20: error: invalid initialization of reference of type PQCell*& from expression of type PriorityQueue*
insertCell(q, x, p);
pqueue.cpp:54:6: error: in passing argument 1 of void insertCell(PQCell*&, ItemType, PriorityType)
void insertCell(PQCell*& L, ItemType x, PriorityType p)
Again, any help would be great, thanks.
The main problem (the one that's causing the invalid initialization error) is that you're passing a PriorityQueue& into a function that's expecting a PQCell*&:
//Function insert inserts item x with priority p into a priority queue 'q'.
void insert(PriorityQueue& q, ItemType x, PriorityType p)
{
// Wrong.
//insertCell(q, x, p);
// You probably meant to do this:
insertCell(q.cells, x, p);
}
I also noticed that your isEmpty logic seems to be backwards:
//Function isEmpty returns true if the queue is empty and false if it is not.
bool isEmpty(const PriorityQueue& q)
{
if(q.cells == NULL)
{
return false;
}
return true;
}
You're returning false if q.cells == NULL, when you probably meant to be returning true in that case, and false otherwise.
Related
I am to implement a Circular Array Queue But I a having logical errors and I am not getting the correct result. I need help implementing bool dequeue() in ArrayQueueP4.h. I doubt if it is correct.
.
I have tried different solutions as well as search through previous questions on stack overflow and online yet it did not give me any ideas on what I am looking for
#ifndef ARRAY_QUEUE_P4_
#define ARRAY_QUEUE_P4_
#include "QueueInterface.h"
#include "PrecondViolatedExcept.h"
template<class ItemType>
class ArrayQueueP4 : public QueueInterface<ItemType>
{
private:
static const int DEFAULT_CAPACITY = 50;
ItemType items[DEFAULT_CAPACITY + 1]; // Array of queue items
int front; // Index to front of queue
int back; // Index to back of queue
public:
ArrayQueueP4() : front(DEFAULT_CAPACITY),
back(DEFAULT_CAPACITY) {};
// Copy constructor and destructor supplied by compiler
bool isEmpty() const;
bool enqueue(const ItemType& newEntry);
bool dequeue();
/** #throw PrecondViolatedExcept if queue is empty. */
ItemType peekFront() const;
};
ArrayQueueP4.h is the header file for ArrayQueueP4.cpp
#include "ArrayQueueP4.h";
#include "PrecondViolatedExcept.h";
using namespace std;
template <class ItemType>
bool ArrayQueueP4 <ItemType>::isEmpty() const {
return (front == back);
}
template <class ItemType>
bool ArrayQueueP4 <ItemType>::enqueue(const ItemType& newEntry) {
if (!isEmpty())
back = (back + 1) % DEFAULT_CAPACITY;
items[back] = newEntry;
back++;
return true;
}
template<class ItemType>
bool ArrayQueueP4 <ItemType> ::dequeue() {
bool result = false;
if (!isEmpty()) {
front = (front + 1) % DEFAULT_CAPACITY;
front--;
result = true;
}
return result;
}
template<class ItemType>
ItemType ArrayQueueP4<ItemType>::peekFront() const {
if (isEmpty())
throw PrecondViolatedExcept("peekFront() called with an empty queue.");
else
return items[front];
}
HERE is my main file main.cpp to test my code
#include <iostream>
#include "ArrayQueueP4.cpp";
using namespace std;
int main() {
ArrayQueueP4<int> AP;
AP.enqueue(1);
AP.enqueue(2);
AP.enqueue(3);
/*LinkedQueueP1<int> LP;
LP.enqueue(1);
LP.enqueue(2);*/
cout << "PEEK FRONT: " << AP.peekFront();
//cout << "PEEK FRONT: " << LP.peekFront();
system("pause");
return 0;
}
Based on my main program file, the output supposed to now 1 when I call the enqueue function. But instead of getting 2 as my answer, I am getting -858993460 as my result when I delete the first item using dequeue(). I do not know if that is how Queues behave but isn't the second number supposed to be the next first item in line when I delete the first number?
According to your description, your front and back defines a range, such that front is the first element available in the queue, and back is the "pass-the-end" index. Then according to those definition the code should look like this:
template <class ItemType>
bool ArrayQueueP4 <ItemType>::enqueue(const ItemType& newEntry) {
// Check if queue is full
if ((back + 1) % (DEFAULT_CAPACITY + 1) == front) return false;
// Append element at one-pass-end position
items[back] = newEntry;
// Update the one-pass-end index (back)
// All your modulo operation should be dealing with DEFAULT_CAPACITY + 1
// because that is the size of your array
back = (back + 1) % (DEFAULT_CAPACITY + 1);
return true;
}
template<class ItemType>
bool ArrayQueueP4 <ItemType> ::dequeue() {
// Dequeue fail if the queue is empty
if (isEmpty()) return false;
front = (front + 1) % (DEFAULT_CAPACITY + 1);
return true;
}
Also, as a reminder, your code does not take resource management in to account (although it works for most types and doesn't seem to make any mistakes). When an item is dequeued, it's corresponding resources should be released. As an exercise, think about the scenario where ItemType is std::unique_ptr (or std::shared_ptr). This is probably not what your teacher wants, but it is a good practice.
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;
}
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.
I have a code to remove the first element of a string array.But its deleting the last entered element.How do I delete the first element in the queue without using STL and how do I reset the queue to empty.Here is my class declaration as Queue.h file and QueueImpl.h as its a template file.You got to include all the functions implemented in Queueimpl.h file and then include it in main.I have successfully deleted the element from the queue and I can see that when printing queue but while searching it, the deleted element still exists why is it that
Queue.h
template <class Type>
class Queue
{
private:
int counter;
int Queue_size;
Type* Contents;
int Front, Back;
int items_in_queue = 0;
public:
Queue(int queue_size = 10);
~Queue();
bool Empty() const;
bool Full() const;
void Remove();
int Add(const Type& new_element);
int QueueSize();
Type front();
int search(string &element,int numElm);
void clear();
bool IsDigitsOnly(string &strn);
};
#endif
QueueImpl.h
#pragma once
#ifndef QUEUETEMPLATE_H
#define QUEUETEMPLATE_H
#include<string>
#include "queue.h"
const int MAX_SIZE = 10;
// Constructor
int counter = 0;
template<class Type>
Queue<Type>::Queue(int queue_size) :
Queue_size(queue_size),
Contents(new Type[queue_size + 1]),
Front(0), Back(0)
{}
// Destructor
template<class Type>
Queue<Type> :: ~Queue()
{
delete[] Contents;
}
// Tests
template<class Type>
void Queue<Type>::clear()
{
while (!Empty()) {
Front = Back = -1;
}
}
template<class Type>
bool Queue<Type>::Empty() const
{
return (Front == Back) ? true : false;
}
template<class Type>
bool Queue<Type>::Full() const
{
return ((1 + Back) % (Queue_size + 1) == Front) ? true : false;
}
/
}
#endif
Ok, now it is enough. I do not want to criticize your code style. It would be better if you would demonstrate an example of usage. Without it I assume Type is std::string. I remove <Type> for simplifications. Let start.
IsDigitsOnly does not relate to your class. It is better to move it into a separate function.
Why you need queue_size + 1 of elements in the array Contents if queue_size is desired?
The constructor Queue::Queue initializes an empty queue object, zeros Front and Back. It should be done in Queue::clear: Front = Back = 0 instead of Front = Back = -1.
Simply return Front == Back instead of return (Front == Back) ? true : false.
Queue::Full would be identical to Queue::Empty. They both should check counter.
Queue::Remove: the condition if (Front == Back) is always false, since the same condition is in if (Empty()). The final else is right, since you are using correct Queue_size. You must counter-- there.
In Queue::Add the erroneous Queue_size + 1 is used.
Queue::search does not use Front and Back therefore it is wrong. See below.
Let stop here. I hope you are able to move forward yourself.
New to the 5 and 8.
template<class Type>
bool Queue<Type>::Empty() const
{
return counter == 0;
}
template<class Type>
bool Queue<Type>::Full() const
{
return counter == Queue_size;
}
template<class Type>
int Queue<Type>::search(const Type& element, int numElm)
{
if (numElm < Front || numElm >= Back)
return -1;
// Used as a subscript to search array
for (int index = numElm; index != Back; index = (index + 1) % Queue_size)
{
if (Contents[index] == element) // If the value is found
return index;
}
return -1;
}