-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!
I'm trying to print each node in a linked list from tail to head using recursion. But why I can't use the highlighting code to realize a recursion?
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
if(!head)
{
vector<int> a(0);
return a;
}
else if(!head -> next)
{
vector<int> a(1, head -> val);
return a;
}
else
/*
return printListFromTailToHead(head -> next).push_back(head -> val);
*/
}
};
If you want to print, then print - don't build a vector.
void printListFromTailToHead(ListNode* head)
{
if (head)
{
printListFromTailToHead(head->next);
std::cout << head->val << '\n';
}
}
If you actually don't want to print anything but produce a vector, you need to rearrange the code a little bit, because push_back does not return anything:
vector<int> reverse_list(ListNode* head)
{
if (!head)
{
return vector<int>{};
}
else // You don't need a special case for a one-element list.
{
vector<int> ls = reverse_list(head->next);
ls.push_back(head->val);
return ls;
}
}
Your function outputs nothing. And it is a bad idea to use a vector to output recursively a list.
The function can look for example the following way as it is shown in a demonstrative program below.
#include <iostream>
struct ListNode
{
int value;
ListNode *next;
};
void push_front( ListNode * &head, int value )
{
head = new ListNode { value, head };
}
std::ostream & printListFromHeadToTail( ListNode * &head, std::ostream &os = std::cout )
{
return head == nullptr ? os
: ( os << head->value << ' ', printListFromHeadToTail( head->next, os ) );
}
std::ostream & printListFromTailToHead( ListNode * &head, std::ostream &os = std::cout )
{
return head == nullptr ? os
: ( printListFromTailToHead( head->next, os ), os << head->value << ' ' );
}
int main()
{
const int N = 10;
ListNode *head = nullptr;
for ( int i = 0; i < N; i++ ) push_front( head, i );
printListFromHeadToTail( head ) << '\n';
printListFromTailToHead( head ) << '\n';
return 0;
}
Its output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
Check out this solution, maybe isn't the better way to do it, but you maybe can take the idea. The thing is, you do not need return an array, also I did not get it why are you returning an vector, you could just call the function again and then print it like the code bellow.
#include <iostream>
using namespace std;
class ListNode {
public:
ListNode *next;
int value;
ListNode() {
this->next = NULL;
this->value = 0;
}
ListNode(int _v) {
this->next = NULL;
this->value = _v;
}
};
void printListNodeFromTailToHead(ListNode *node) {
// If the current node is null will
// exit the recursive function
if (node == NULL) return ;
// Else will call the function again with next ListNode
// and print the current value
printListNodeFromTailToHead(node->next);
cout << node->value << endl;
}
int main() {
ListNode *a = new ListNode(1);
ListNode *tmp = a;
for (int i = 2; i < 10; i++) {
a->next = new ListNode(i);
a = a->next;
}
printListNodeFromTailToHead(tmp);
return 0;
}
I'm trying to print each node in a linked list from tail to head using
recursion
Because you provide no info about your list, here I will show you a simple implementation of your desired function(s) using a "std::list". Note that the recursion I provide has no function parameters, no global scope vars, and no static vars (and I use cout, not print).
Also, I use a class form known as a Functor. I recommend them for encapsulating 'small' function(s). Please review literature on functors ... I consider them 'simpler' than the typical class.
#include <iostream>
using std::cout, std::cerr, std::endl, std::flush; // c++17
using std::ostream;
#include <list>
using std::list;
#include <string>
using std::string, std::to_string;
// typedefs are often simpler to read
// user typedefs ---------------vvvvvvvvvvv
typedef list<string> StrList_t;
typedef list<string>::iterator StrListIt_t;
// Functor
class F820_Recursive_t
{
// data attributes of class instance are not global nor static vars
StrList_t m_strList;
StrListIt_t m_it;
public:
int operator()() { return exec(); } // Functor entry
private:
int exec() // builds and modifies a std::list<string>
{
// example: using initializer list syntax
m_strList = StrList_t { "111", "222", "333", "444", "555", "666", "777", "888" };
recurseAndReportSize();
// example: appending to existing list
for (int i=301; i<309; ++i) {
string s = "S" + to_string(i);
m_strList.push_back (s);
}
recurseAndReportSize();
cout << "\n version cplusplus: " << __cplusplus << "\n\n" << endl;
return 0;
}
void recurseAndReportSize()
{
if (0 == m_strList.size()) {
cout << "\n empty list" << flush;
return;
}
cout << "\n\n recurse over list to count elements ... " << flush;
m_it = m_strList.begin(); // head to tail
uint count = recurseCount();
// report
cout << count << " elements" << endl;
// report list contents head to tail
m_it = m_strList.begin();
cout << "\n Head to Tail recursive content report "
<< "\n [" << coutListFromHeadToTail() << "]" << endl;
// report list contents tail to head
m_it = m_strList.end(); m_it--;
cout << "\n Tail to Head recursive content report: "
<< "\n [" << coutListFromTailToHead() << "]" << endl;
}
// recurse with no parameters, no static vars, no global vars
uint recurseCount( )
{ // --^-- no parameters
if (m_it == m_strList.end()) // RTC (recursion termination clause)
return 0;
m_it++; // step to next element
return (1 + recurseCount()); // tail recursion
}
// recurse with no parameters, no static vars, no global vars
string coutListFromHeadToTail ( )
{ // --^-- no parameters
cout << *m_it++;
if (m_it == m_strList.end()) // RTC (recursion termination clause)
return "";
cout << ", ";
return coutListFromHeadToTail(); // tail recursion
}
// recurse with no parameters, no static vars, no global vars
string coutListFromTailToHead ( )
{ // --^-- no parameters
if (m_it == m_strList.begin()) {
cout << *m_it;
return "";
}
cout << *m_it << ", ";
m_it--;
return coutListFromTailToHead(); // tail recursion
}
}; // class F820_Recursion_t
int main(int, char**) { return F820_Recursive_t()(); }
Output on my Lubuntu 19.04, g++ v8.3
recurse over list to count elements ... 8 elements
Head to Tail recursive content report
[111, 222, 333, 444, 555, 666, 777, 888]
Tail to Head recursive content report:
[888, 777, 666, 555, 444, 333, 222, 111]
recurse over list to count elements ... 16 elements
Head to Tail recursive content report
[111, 222, 333, 444, 555, 666, 777, 888, S301, S302, S303, S304, S305, S306, S307, S308]
Tail to Head recursive content report:
[S308, S307, S306, S305, S304, S303, S302, S301, 888, 777, 666, 555, 444, 333, 222, 111]
version cplusplus: 201703
i will be using linked list example code seen here on stackoverflow to illustrate the problem.
my c++ written progam (x64) contains this linked list code :
old code snippets deleted; im sorry if comments doesnot make sense anymore.
added fully working code to show what my problem is.
compile : g++ linkedlist.cpp -o linked-list
#include <cstdlib>
#include <iostream>
using namespace std;
struct node
{
public :
unsigned int part1; // 4 bytes
unsigned int part2; // 4 bytes
node *next; //pointer, 8 bytes on 64 bit system
unsigned int read_part1();
};
struct LinkedList
{
public:
LinkedList();
void insert(unsigned int data[], unsigned int data1);
bool isEmpty() const;
node* head;
};
unsigned int node::read_part1() {
return part1;
}
LinkedList::LinkedList():
head(NULL)
{
}
bool LinkedList::isEmpty() const
{
return (head == NULL);
}
void LinkedList::insert(unsigned int data[], unsigned int data1)
{
node* oldHead = head;
node* newHead = new node();
newHead->part1 = data[0];
newHead->part2 = data1;
newHead->next = oldHead;
head = newHead;
}
unsigned int allocations = 300000000;
unsigned int index_size = 430000000;//index of lists, 430m,.
//will be creatad on heap
LinkedList *list = NULL;
int main(int argc, char *argv[])
{
LinkedList list_instance;
cout << "1 LinkedList instance takes [" << sizeof(list_instance) << "] bytes in memory!"<< endl;
node node_instance;
cout << "1 node instance takes [" << sizeof(node_instance) <<"] bytes in memory !"<< endl;
try{
list = new LinkedList[index_size];
}
catch(std::bad_alloc) {
cout << "Error allocating memory" << endl;
return 0;
//reboot code
}
unsigned int some_data[] = {00, 01};
unsigned int index;
LinkedList *list_instance2 = NULL;
cout << "Allocating ..." << endl;
for (int i=0; i<allocations; i++)
{
index = rand();
unsigned short inde = (unsigned short)index;
list_instance2 = &list[inde];
list_instance2->insert(some_data, some_data[1]);
}
unsigned long sk = ((allocations * sizeof(node_instance) + index_size*sizeof(list_instance))) / (1024*1024*1024);
cout << "This process *should* consume around " << sk <<" GBytes of memory, but does it ?"<< endl;
cout << "Allocating done, *check the process size* and press any number key + ENTER to exit ..." << endl;
int u=0;
cin >> u;
return 0;
}
compile it, run it and see if your process size even remotely matches whats expected.
if not - where is the problem ?
oh, and i run it on 64 bit slackware 13.37 with a unmodified default kernel.
On my box, with slightly modified source (see below with notes)
it uses 1243 MiB rather than the 'expected' 785 MiB using the standard library heap routines
it uses 791 MiB when using Google's tcmalloc
it uses 840 MiB when using Boost Object Pool to allocate nodes (with standard library heap or tcmalloc)
The overhead is very clearly in the implementation of the heap routines.
Here's the code:
Note the use of new (nothrow) there.
Also, the baseline measurement at the start (I used pmap $(pgrep test) | tail on linux)
Note the choice in insert:
void LinkedList::insert(unsigned int data[], unsigned int data1)
{
#if 1
head = new node { data[0], data1, head };
#else
static boost::object_pool<node> node_pool;
node* add = node_pool.malloc();
*add = node { data[0], data1, head };
head = add;
#endif
}
Change #if 1 to #if 0 to use the Boost Object Pool
There was a strangeness in the node allocation loop
index = rand();
unsigned short inde = (unsigned short)index;
list_instance2 = &list[inde];
list_instance2->insert(some_data, some_data[1]);
I changed it to what you probably intended:
list[rand() % index_size].insert(some_data, some_data[1]);
#include <stdlib.h>
#include <iostream>
#include <boost/pool/object_pool.hpp>
using namespace std;
struct node
{
unsigned int part1; // 4 bytes
unsigned int part2; // 4 bytes
node *next; //pointer, 8 bytes on 64 bit system
};
struct LinkedList
{
public:
LinkedList();
void insert(unsigned int data[], unsigned int data1);
bool isEmpty() const;
node* head;
};
LinkedList::LinkedList():
head(NULL)
{
}
bool LinkedList::isEmpty() const
{
return (head == NULL);
}
void LinkedList::insert(unsigned int data[], unsigned int data1)
{
#if 1
head = new node { data[0], data1, head };
#else
static boost::object_pool<node> node_pool;
node* add = node_pool.malloc();
*add = node { data[0], data1, head };
head = add;
#endif
}
const unsigned int allocations = 30000000;
const unsigned int index_size = 43000000;//index of lists
//will be creatad on heap
LinkedList *list = NULL;
int main(int argc, char *argv[])
{
LinkedList list_instance;
cout << "1 LinkedList instance takes [" << sizeof(list_instance) << "] bytes in memory!"<< endl;
node node_instance;
cout << "1 node instance takes [" << sizeof(node_instance) <<"] bytes in memory !"<< endl;
cout << "Before dynamic allocations: *check the baseline process size* and press ENTER to start allocating ..." << endl;
std::string s;
std::getline(std::cin, s);
list = new (nothrow) LinkedList[index_size];
if (!list)
{
cout << "Error allocating memory" << endl;
return 1;
}
unsigned int some_data[] = {00, 01};
cout << "Allocating nodes ..." << endl;
for (unsigned int i=0; i<allocations; i++)
{
list[rand() % index_size].insert(some_data, some_data[1]);
}
unsigned long sk = ((allocations * sizeof(node_instance) + index_size*sizeof(list_instance))) >> 20;
cout << "This process *should* consume around " << sk <<" MiB of memory, but does it ?"<< endl;
cout << "Allocating done, *check the process size* and press ENTER to exit ..." << endl;
std::getline(std::cin, s);
return 0;
}