How to print the lead of A* algorithm - c++
-I wrote a program to find the shortest path from a source node to a target node. Everything is fine, the program found the shortest path. But i have a problem, that is not able to print or get each node in the path. I tried many ways but no result. Hope anyone can help me, thanks everyone.
///////////////////////////////
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
typedef struct Node
{
int vertex;
int g;
int h;
int f;
Node* parent;
Node(int vertex)
{
this->vertex = vertex;
this->g = 0;
this->h = 0;
this->f = 0;
this->parent=NULL;
}
Node(int vertex,int g, int h, int f,Node*parent)
{
this->vertex = vertex;
this->g = g;
this->h = h;
this->f = f;
this->parent = parent;
}
}Node;
struct Edge
{
int source;
int dest;
int g;
int h;
};
struct comp
{
bool operator()(const Node* lhs, const Node* rhs) const {
return lhs->f < rhs->f;
}
};
std::vector<Node*>openList;
std::vector<Node*>closeList;
Node* startPos;
Node* endPos;
static const int WeightW = 10;
class Graph
{
public:
std::vector<std::vector<Edge>>adjlist;
Graph(const std::vector<Edge>& edges, int N)
{
adjlist.resize(N);
for (auto &edge:edges)
{
adjlist[edge.source].push_back(edge);
}
}
};
int isContains(std::vector<Node*>* Nodelist, int vertex);
void printPath(Node*node);
void findShortestPath(const Graph& grap,Node* start,Node* end, int N)
{
Node* node;
openList.push_back(start);
while (openList.size()>0)
{
node = openList[0];
closeList.push_back(node);
openList.erase(openList.begin());
std::cout << "start" << std::endl;
int u = node->vertex;
std::cout << "V: " << u << " g :" << node->g << std::endl;
std::cout << "continous" << std::endl;
for (auto v : grap.adjlist[u])
{
if (v.dest == end->vertex)
{
std::cout << "FindNode " << v.dest << std::endl;
printPath(node);
return;
}
if (isContains(&closeList, v.dest) == -1)
{
if (isContains(&openList, v.dest) == -1)
{
int vertex = v.dest;
std::cout <<"V: "<< vertex << std::endl;
int h = v.h;
int currentg = node->g + v.g;
int f = currentg + h;
std::cout <<"vertext: "<<vertex<< " h: " << h << " g: " << currentg << " f: " << f << std::endl;
Node* newNode = new Node(vertex, currentg, h, f,node->parent);
openList.push_back(newNode);
}
}
}
std::cout<<"Close: ";
for (size_t i = 0; i < closeList.size(); i++)
{
std::cout << closeList[i]->vertex << " ";
}
std::cout << std::endl;
sort(openList.begin(), openList.end(),comp());
std::cout << "Open: ";
for (size_t i = 0; i < openList.size(); i++)
{
std::cout << openList[i]->vertex << " ";
}
std::cout << std::endl;
std::cout << "end" << std::endl;
std::cout << std::endl;
}
}
void printPath(Node* node)
{
std::cout << std::endl;
if (node->parent != NULL)
printPath(node->parent);
std::cout << node->vertex << " ";
}
int isContains(std::vector<Node*>* Nodelist,int vertex)
{
for (int i = 0; i < Nodelist->size(); i++)
{
if (Nodelist->at(i)->vertex== vertex)
{
return i;
}
}
return -1;
}
int main()
{
//{Node,Node,G,H}
//Firt Node
//second Node
//G is the movement cost to move from the starting point to a given square on the grid
// following the path generated to get there
//H is the estimated movement cost to move from that given square on the grid to the final destination
std::vector<Edge>edges =
{
{0,1,5,17},
{0,2,5,13},
{1,0,5,16},
{1,3,3,16},
{1,2,4,13},
{2,0,5,16},
{2,1,4,17},
{2,3,7,16},
{2,4,7,16},
{2,7,8,11},
{3,2,7,13},
{3,7,11,11},
{3,10,16,4},
{3,11,13,7},
{3,12,14,10},
{4,2,7,13},
{4,5,4,20},
{4,7,5,11},
{5,4,4,16},
{5,6,9,17},
{6,5,9,20},
{6,13,12,7},
{7,3,11,16},
{7,4,5,16},
{7,8,3,10},
{8,7,3,11},
{8,9,4,8},
{9,8,4,10},
{9,13,3,7},
{9,15,8,0},
{10,3,16,16},
{10,11,5,7},
{10,13,7,7},
{10,15,4,0},
{11,3,13,16},
{11,10,5,4},
{11,12,9,10},
{11,14,4,5},
{12,3,14,16},
{12,11,9,7},
{12,14,5,5},
{13,9,3,8},
{13,10,7,4},
{13,15,7,0},
{14,11,4,7},
{14,12,5,10},
{15,9,8,8},
{15,10,4,4},
{15,13,7,7},
};
int n = edges.size();
Graph grap(edges, n);
//std::cout << h << std::endl;
Node* start = new Node(0);
Node* end = new Node(15);
findShortestPath(grap, start, end, n);
//Astar astar;
//Node* startPos = new Node(5, 1);
//Node* endPos = new Node(1, 8);
//astar.printMap();
//astar.search(startPos, endPos);
//cout << endl;
//astar.printMap();
system("pause");
return 0;
}
Your program doesn't find the shortest path. It gives the wrong output. (you're on the right track though)
I will assume you are trying to find the shortest path by using BFS. Let's take a look at line 113:
sort(openList.begin(), openList.end(),comp());
Here you're sorting your BFS queue (vector in your case) and thus destroying the right order.
Delete that line.
Congrats, now your program finds the shortest path!
Next, as I understand, for each node you branch into, you remember which node you came from in order to backtrack the path once you reach the destination or final node.
In line 102:
Node* newNode = new Node(vertex, currentg, h, f,node->parent);
you are assigning the new node's grandparent instead of parent. Change that line to
Node* newNode = new Node(vertex, currentg, h, f,node);
Now your printPath function works properly and prints the right path. (just add the target node)
Anyways, your code has a lot of space for improvements. Check out other implementations online and try to see if you can code it as short and clean for practice. Good luck!
Related
C++ Code crashing when I reference a file
You can see by the "In what file is the data for the graph contained?" prompt, that I have to input a file to get the code to function properly. The program gets up to "In what file is the data for the graph contained?", then I input a file name, it freezes then crashes. My whole computer freezes and other applications begin to crash. I even ran the code by removing my own code, and the same problem occurs. What is causing this? And how can I fix this? #include <fstream> #include <iostream> using namespace std; struct edge { struct vertex* Vertex; int weight; edge* nextedge; edge(edge* e = 0, struct vertex* v = 0, int w = 0) { Vertex = v; weight = w; nextedge = e; } }; struct vertex { char name; vertex* nextvertex; edge* edgelist; int index; bool final; vertex* pre; vertex(char n = '\0', vertex* v = 0) { name = n; nextvertex = v; edgelist = 0; index = -1; final = false; pre = 0; } }; int main() { char input_file[128]; cout << "In what file is the data for the graph contained?\n> "; cin.getline(input_file, 128); ifstream infile(input_file); vertex* graph = 0; vertex *startptr = 0, *finishptr = 0; vertex *vertexsearch = 0, *vptr = 0; vertex* last; vertex* w; edge* edgeptr = 0; int weight; char start, finish, comma; bool startnotfound = true, finishnotfound = true; infile >> start >> comma >> finish >> comma >> weight; while (!infile.eof()) { /* build the edge list */ startptr = new vertex(sizeof(struct vertex)); finishptr = new vertex(sizeof(struct vertex)); finishptr->name = finish; startptr->name = start; startptr->nextvertex = finishptr; edgeptr = new edge(); edgeptr->Vertex = startptr; edgeptr->weight = weight; edgeptr->nextedge = NULL; graph = new vertex(sizeof(struct vertex)); graph->name = finish; graph->edgelist = edgeptr; } // Output the graph vptr = graph; while (vptr) { cout << vptr->name << '\n'; edgeptr = vptr->edgelist; while (edgeptr) { cout << " Edge to " << edgeptr->Vertex->name << " with weight " << edgeptr->weight << '\n'; edgeptr = edgeptr->nextedge; } vptr = vptr->nextvertex; } // From where to where cout << "From where: "; cin >> start; cout << "to where: "; cin >> finish; vertex* s = graph; startptr = finishptr = 0; while (s) { if (s->name == start) { startptr = s; } if (s->name == finish) { finishptr = s; } s = s->nextvertex; } if (!startptr) { cout << "Start point given is not a valid vertex.\n"; return 1; } last = startptr; last->index = 0; last->final = true; while (!(finishptr->final)) { /* Search for shortest path */ } vptr = finishptr; if (vptr->pre) while (vptr) { cout << vptr->name << '\n'; vptr = vptr->pre; } else cout << "No such path.\n"; return 0; }
Exception thrown: write access violation
I am trying to implement a list structure, but when I wrote the insert() function which inserts an element in a specific position in the list, I get an error Exception thrown: write access violation. pl was 0x34812B3A. I tried alot to fix it but I really can't. I used try..throw..catch and still didn't get it, so what should I do. This is my code: List.h #pragma once #define MAXLIST 100 typedef struct List { int size; int entry[MAXLIST]; }list; void createl(list*); int ListEmpty(list*); int ListFull(list*); int sizel(list*); void destroyl(list*); void insert(int, int, list*); void deletei(int* , int, list*); void traversel(list*, void (*)(int)); void retrieve(int*, int, list*); void replace(int, int, list*); //int access(int , list*); and this is the implementation (List.cpp) #include <iostream> #include "List.h" using namespace std; void createl(list* pl) { pl->size = 0; } int isEmpty(list* pl) { return !(pl->size); } int isFull(list* pl) { return (pl->size == MAXLIST); } int sizel(list* pl) { return pl->size; } void destroyl(list* pl) { pl->size = 0; } void insert(int e, int p, list* pl) { //insert element e in the postion p in the list for (int i = pl->size -1; i >= p; i--) { pl->entry[i+1] = pl->entry[i]; } pl->entry[p] = e; pl->size++; } void deletei(int* pe, int p, list* pl) { *pe = pl->entry[p]; for (int i = p + 1; i < pl->size; ++i) { pl->entry[i-1] = pl->entry[i]; } pl->size--; } void traversel(list* pl, void (*pf)(int e)) { for (int i = 0; i < pl->size; ++i) { (*pf)(pl->entry[i]); } } void retrieve(int* pe, int p, list* pl) { *pe = pl->entry[p]; } void replace(int e, int p, list* pl) { pl->entry[p] = e; } /*int access(int p, list* pl) { return pl->entry[p]; }*/ I get the error here in function insert() pl->entry[p] = e; and this is a program to just check if my code works. #include <iostream> #include "List.h" using namespace std; void display(int e) { cout << e << "\n"; } int main() { list l; list* ptl = &l; int t; cout << "Put 5 elements:\n"; for (int i = 0; i < 5; ++i) { cin >> t; insert(t, sizel(ptl), ptl); } cout << "The list looks like a stack\n\n"; traversel(ptl, display); cout << "The size of the list is: " << sizel(ptl) << endl; insert(9, 2, ptl); cout << "The size of the list is: " << sizel(ptl) << endl; int temp; deletei(&temp, 2, ptl); cout << temp <<endl ; traversel(ptl, display); cout << "The size of the list is: " << sizel(&l) << endl; int t2; retrieve(&t2, 2, ptl); cout << t2 << endl; replace(4, 1, ptl); traversel(ptl, display); destroyl(ptl); cout << "The size of the list is: " << sizel(ptl) << endl; return 0; } Thank you for your time and helping me.
You used ptl, which points at l, without initializing l. Add initialization like this: int main() { list l; list* ptl = &l; int t; createl(ptl); // add initialization cout << "Put 5 elements:\n"; for (int i = 0; i < 5; ++i) { cin >> t; insert(t, sizel(ptl), ptl); }
VS Code not showing local variables at all
I am using VS code for coding in C++. The problem arises when I try to debug a code and set a breakpoint. The local variables pane doesn't show any variables at all. Sometimes it does show some variables but not all of them. Also when I try to close the debugger and click on the stop button, it does not stop. It requires me to click on it multiple times, which I think means, that multiple debuggers are opened or something like that. To reproduce this problem, save this text as input_static.txt. T1 1 2 5 T2 2 4 T3 2 3 T4 1 2 4 T5 1 3 T6 2 3 T7 1 3 T8 1 2 3 5 T9 1 2 3 And debug the following code by setting a breakpoint at line number 201. #include <bits/stdc++.h> using namespace std; ifstream fin; ofstream fout; typedef struct fptnode { int item, count; fptnode *next; map<int, fptnode *> children; fptnode *parent; fptnode(int item, int count, fptnode *parent) { this->item = item; this->count = count; this->parent = parent; } } * FPTPTR; map<int, int> frequency; bool isMoreFrequent(int a, int b) { if (frequency[a] == frequency[b]) return a < b; return frequency[a] > frequency[b]; } class FPTREE { public: FPTPTR root; map<int, list<FPTPTR>> headers; // map<int, int> frequency; FPTREE() { this->root = new fptnode(-1, 0, NULL); } // class isMoreFrequent // { // public: // FPTREE *T; // isMoreFrequent(FPTREE *T) // { // this->T = T; // } // bool operator()(int item1, int item2) // { // return T->frequency[item1] > T->frequency[item2]; // } // }; FPTPTR getNewNode(int item, int count, fptnode *parent) { FPTPTR T = new fptnode(item, count, parent); this->headers[item].push_back(T); return T; } void add(vector<int> &transaction) { stack<int> S; std::sort(transaction.begin(), transaction.end(), isMoreFrequent); for (int i = transaction.size() - 1; i >= 0; i--) { S.push(transaction[i]); } insert(root, S); } int insert(FPTPTR T, stack<int> &S) { T->count++; if (S.empty()) return 0; int top = S.top(); S.pop(); if (T->children[top] == NULL) { T->children[top] = getNewNode(top, 0, T); } insert(T->children[top], S); return 0; } void printPreOrder(ofstream &fout) { printPreOrder(fout, this->root); } void printPreOrder(ofstream &fout, FPTPTR T) { if (T) { fout << "[" << T->item << ", " << T->count << "]" << ' '; for (auto p : T->children) { printPreOrder(fout, p.second); } } } void printTree(ofstream &fout) { printTree(fout, this->root); } void printTree(ofstream &fout, FPTPTR T, int level = 0) { if (T) { for (int i = 0; i < level; i++) fout << "\t"; fout << "[" << T->item << ", " << T->count << "]" << endl; for (auto p : T->children) { printTree(fout, p.second, level + 1); } } } void generatePath(FPTPTR node, vector<int> &path) { if (node && node->item >= 0) { path.push_back(node->item); generatePath(node->parent, path); } } FPTREE newTree(int item) { list<FPTPTR> &nodes = this->headers[item]; vector<int> patternBase; FPTREE f; for (auto node : nodes) { patternBase.clear(); generatePath(node->parent, patternBase); for (int j = 0; j < node->count; ++j) f.add(patternBase); } return f; } int clear() { return this->clear(this->root); } int clear(FPTPTR T) { for (auto p : T->children) { clear(p.second); } return 0; } bool isEmpty() { // return this->root->count == 0; return this->root->children.empty(); } } F; ofstream tempout; map<set<int>, int> mine(FPTREE f, int r = -1) { map<set<int>, int> M; if (!f.isEmpty()) { // if (f.root->children.empty()) // M[{}] += f.root->count; tempout << "\nOn removing " << r << ":\n"; f.printTree(tempout); for (auto p : frequency) { FPTREE subF = f.newTree(p.first); map<set<int>, int> m = mine(subF, p.first); for (auto q : m) { auto itemset = q.first; itemset.insert(p.first); M[itemset] += q.second; } subF.clear(); } return M; } // tempout << "\nTerminated.\n"; return {}; } int main(int argc, char const *argv[]) { fin.open("input_static.txt"); fout.open("output_static.txt"); tempout.open("temp"); string str, s; while (fin >> s) { if (s.front() != 'T') { frequency[stoi(s)]++; } } vector<int> transaction; stringstream st; fin.clear(); fin.seekg(0); while (std::getline(fin, str)) { st.clear(); st.str(str); transaction.clear(); while (st >> s) { if (s.front() != 'T') { transaction.push_back(stoi(s)); } } F.add(transaction); } fout << "Preorder:\n"; F.printPreOrder(fout); fout << endl << endl; fout << "Tree in directory form:\n"; F.printTree(fout); // printPrefixes(5); map<set<int>, int> frequentItemsets = mine(F); fout << endl; for (auto p : frequentItemsets) { fout << "Frequency=" << p.second << "\t"; for (int item : p.first) { fout << item << ' '; } fout << endl; } // for (int i = 1; i <= 5; ++i) // { // fout << i << ":\n"; // FPTREE f = F.newTree(i); // f.printTree(); // } // F.newTree(1).newTree(2).printTree(fout); return 0; } If it helps this is a program to generate and mine an FP-tree to find frequent itemsets in a transactional database.
EXC_BAD_ACCESS pointer C++
This is by far the most frustrating error I have come across while programming in C++. Here is the code I am trying to run. Every time I run it, it gives me bad access error and when I try to debug it with LLDB, it shows that value of every member in end = 0 and gives the bad access pointer error. Please let me know what's the solution to the current problem. I have been stuck on this for a while now and I come across this error every now and then so any debugging tips would be appreciated. struct edge; struct node { int id; double longitude; double latitude; double distance; string state; string name; vector<edge*>r; int prio; }; struct edge { string name, type; double dist; node* x; node* y; void print() { cout << name << " " << type << " "<< dist << " miles" << " from " << x->id << " to " << y->id << endl; } edge(node* x, node* y, double dist, string name) { this->x = x; this->y = y; this->dist = dist; this->name = name; } edge(){}; }; struct route{ int place1; int place2; string rt; string vert; double lengt; route(int o, int d, double l,string r ){ place1 = o; place2 = d; rt =r; lengt=l; } }; struct compPair { bool operator()(node* a, node* b) { return a->prio > b->prio; } }; void SPT(vector<node*> & g, int from, int to){ priority_queue <node *, vector<node*>, compPair> pq; g[from]->prio = 0; pq.push(g[from]); while(!pq.empty()){ node* place1 = pq.top();pq.pop(); for(int i=0;i<place1->r.size();i++){ edge* rd = place1->r[i]; node* place2 = rd->x; if(place2==place1){ place2=rd->y; } if(place2->prio == -2){ place2->prio = place1->prio + rd->dist; pq.push(place2); } else if (place2->prio > (place1->prio + rd->dist)){ place2->prio = place1->prio + rd->dist; } } } node* beg = g[from]; node* end = g[to]; if(g[from]->prio < 0 || g[to]->prio < 0){ cout <<"Path does not exist"; return; } //THIS IS BUGGY CODE, everything works fine without this code // node* lowp = end; vector <route*> p; while(beg!=end){ double reallowp = end->prio; edge* rtt = end->r[0]; for(int i =0;i<end->r.size();i++){ edge *r = end->r[i]; node* town1 = r->x; if(town1 == end){ town1 = r->y; } if(town1->prio <= reallowp){ reallowp = town1->prio; lowp = town1; rtt = r; } } route* e = new route(end->id,lowp->id,rtt->dist,rtt->name); p.push_back(e); end=lowp; } for(int i=p.size()-1;i>=0;i--){ cout << "From intersection " << p[i]->place2 << "take " << p[i]->rt << " " << p[i]->lengt << " miles to intersection " << p[i]->place1 << endl; } } int main() { vector<node*>t = readTown(); readRoad(t); SPT(t,68,69); }
Inserting nodes in a Binary Tree recursively?
I am trying to insert nodes in a binary tree recursively, but the code is only doing the root node and it's left and right children. I am trying to figure out how to get past that point. I have already tried different implementations, using queues, doing level order insert. I believe the problem is due to the fact that in my main function I only call with root, and if that is the problem, how would I go about calling with the left and right childs. Main Function: int main() { treenode* root = new treenode(); for(int a = 1; a < 15; a++) { insert(root, a); } cout << "Height: " << height(root) << endl; cout << "Printed Tree: " << endl; for(int a = 0; a <= height(root); a++) { printGivenLevel(root, a); //Print every level cout << endl; } return 0; } Here is my insert function: void insert(treenode*& node, int val) { if(node == nullptr) { node = new treenode(val); return; }else{ if(node->left == nullptr) { insert(node->left, val); }else{ insert(node->right, val); } } } A treenode has a value, a left child and right child: struct treenode { //The value of the node int value; //Pointers to the left and right children treenode *left, *right; //Constructor with values; treenode(int val=0, treenode *l = nullptr, treenode *r = nullptr) : value(val), left(l), right(r) {}; }; I would expect the result to be something like so: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 But my actual output is only: 0 1 2 Thanks in advance
... but the code is only doing the root node and it's left and right children. I am trying to figure out how to get past that point. I find no error in your treenode::insert, your problem might be in some other code you do not show. For example, you did not provide "height(root)" or "Printed Tree" info. I could not diagnose them. I have provided some alternatives for various ideas. see "dump()" and "height()" and "size()". Note: "dump()" is none of pre, in-, or post- order, because the sorted input creates unbalance tree displays (they are worst-case-unbalanced). I found this display the easiest to review. Perhaps the following will help you diagnose your mistakes. Good luck. Note the use of "if(false) cout << ...". These are diagnostic output which might provide some insights by enabling them, and / or adding such items to your code. Did you try your debugger yet? #include <chrono> // short form names----vvvvvvv typedef std::chrono::high_resolution_clock HRClk_t; // std-chrono-hi-res-clk typedef HRClk_t::time_point Time_t; // std-chrono-hi-res-clk-time-point typedef std::chrono::nanoseconds NS_t; // std-chrono-nanoseconds using namespace std::chrono_literals; // suffixes like 100ms, 2s, 30us using std::chrono::duration_cast; #include <iostream> using std::cout, std::endl, std::flush; #include <iomanip> using std::setw; namespace DTB { class treenode { friend class T920_t; int value; //The value of the node treenode *left, *right; //Pointers to the left and right children //Constructor with values; treenode(int val=0, treenode *l = nullptr, treenode *r = nullptr) : value(val), left(l), right(r) { ctor('A'); }; void ctor(char kar) { if (left) left->ctor(kar); { if(false) // diagnostic cout << "\n ctor: " << " " << kar << " val: " << setw(3) << value << flush; } if(right) right->ctor(kar); } void insert ( treenode*& node, int val) { if(node == nullptr) { node = new treenode(val); if (false) node->dump(); // diagnostic return; } else { if(node->left == nullptr) { insert(node->left, val); if (false) node->dump(); // diagnostic } else { insert(node->right, val); if (false) node->dump(); // diaagnostic } } } int height(int lvl = 1) { static int maxHeight = 0; if (left) left->height (lvl+1); if(right) right->height (lvl+1); if (lvl > maxHeight) maxHeight = lvl; return maxHeight; } int size() { int count = 1; // this element if (left) { count += left->size(); }; if(right) { count += right->size(); } return count; } void dump(int lvl=0) { if (left) left->dump (lvl+1); if(right) right->dump (lvl+1); { cout << "\n " // << lvl << setw(3*lvl) << ' ' << value << flush; } } }; // class treenode typedef treenode Node_t; // shorter name for user-defined-type class T920_t { public: int operator()(int argc, char* argv[]) { return exec(argc, argv); } private: int exec(int , char** ) { int retVal = 0; Time_t start_ns = HRClk_t::now(); Node_t* root = new Node_t(); // 1st node for(int v = 1; v < 21; ++v) { // 20 more root->insert(root, v); } cout << "\n\n size : " << root->size() // element count << " maxHeight : " << root->height() << endl; dumpAll(root); for(int v = 1; v < 11; ++v) { // 10 more root->insert(root, v); } cout << "\n\n size : " << root->size() // element count << " maxHeight : " << root->height() << endl; dumpAll(root); auto duration_ns = duration_cast<NS_t>(HRClk_t::now() - start_ns).count(); cout << "\n\n\n T920_t::exec() duration " << duration_ns << " ns " << " cpluplus vers : " << __cplusplus << std::endl; return retVal; } void dumpAll (Node_t*& node) { cout << "\n dumpAll(): "; node->dump(); cout << endl; } }; // class T920_t } // namespace DTB int main(int argc, char* argv[]) { return DTB::T920_t()(argc, argv); } A partial output is: size : 21 maxHeight : 11 dumpAll(): 1 3 5 7 9 11 13 15 17 19 20 18 16 14 12 10 8 6 4 2 0 size : 31 maxHeight : 16 dumpAll(): 1 3 ... 10 8 6 4 2 0 T920_t::exec() duration 271095 ns cpluplus vers : 201703