Graph Traversal Problem - c++

My Dijkstra Algorithm works fine to find a path. Now I want to go back to show the way I went. I mark a visited vertex and give it a pointer to the vertex I came from "prev". Unfortunately these pointers get manipulated in some way when looping in the while loop, so that the vertices at the end don't know where they came from. Can you help me?
Probably it's a pointer problem I don't get. I have a copy constructor and a =operator.
int MyMatrix::searchBreadth(MyVertex &from,MyVertex &to,int mode)
{
queue<MyVertex> q;//queue
vector<MyVertex> nb;//vector of neighbours
path=INFINITY;//path is very long
visits.push_back(from.getName());
from.setDistance(0);
MyVertex n("start");
from.setPrev(n);
q.push(from);
while(!q.empty())
{
MyVertex v=q.front();
q.pop();
int k=v.getDistance();
nb.clear();
nb = getNeighbours(v);
for(unsigned int i=0;i<nb.size();i++)
{
if((!nb[i].getPrev())&&path==INFINITY) nb[i].setPrev(v);
if(!mode){//unweighted
if(!wasVisited(nb[i].getName())){
nb[i].setDistance(k+1);
q.push(nb[i]);
}
}
if(mode){//length or weight
if(!wasVisited(nb[i].getName())){
int cost=0;
MyEdge e = m->getEdge(v,nb[i]);
if(mode==1)cost=(int) e.getLength();//length
if(mode==2)cost=(int) e.getWeight();//weigth
nb[i].setDistance(k+cost);
q.push(nb[i]);
}
}
if((nb[i].getName().compare(to.getName())==0) && (!wasVisited(nb[i].getName()))){//path found
int j=nb[i].getDistance();
if(j<path)path=j;
}
visits.push_back(nb[i].getName());
}//end of for
//end of 0size if
}//end of while
return path;
}
MyVertex::MyVertex()
{
name="null";
dist=0;
visited=false;
prev=0;
}
MyVertex::MyVertex(string name)
{
this->name=name;
visited=false;
dist=numeric_limits<int>::max();
prev=0;
}
MyVertex::~MyVertex(void)
{
if (!prev) prev=0;
}
MyVertex::MyVertex(const MyVertex& V){
this->name = V.name;
this->visited=V.visited;
this->dist=V.dist;
this->prev=V.prev;
}
MyVertex& MyVertex::operator=(const MyVertex& L){
if (this == &L){ return *this;
}else{
delete prev;
dist=L.dist;
name=L.name;
visited=L.visited;
prev=L.prev;
}
return *this;
}

You're leaving a lot of code out, but you seem to be adjusting the Distance of a node -- and setting its prev -- without first checking whether it already has a lesser Distance. And once you've found any path, you stop setting prev, so that if you later find a shorter path, its nodes may not be marked.

Related

What is the problem with this code? It never ends (Top View of a Binary Tree)

Problem Statement : Print the Top view of the binary tree
My approach : I maintain a queue which has a pair inside it each for root->data and horizontal distance(hd). I push the root with the hd in the queue and add it to the map which contains the hd and the root->data. Then I pop from the queue. Now, if there are any children of the popped root, I insert them into the queue and the above procedure keeps on happening until the queue is not empty.
My code :-
void topView(Node * root) {
queue<pair<int, int>> q;
map<int, int> m;
q.push({root->data, 0});
while(q.empty() == false){
int node_val = q.front().first;
int hd = q.front().second;
m[hd] =node_val;
q.pop();
if(root->left){
int hdl = hd -1;
q.push({root->left->data, hdl});
}
if(root->right){
int hdr = hd + 1;
q.push({root->right->data, hdr});
}
}
for(auto i=m.begin();i!=m.end();i++)
{
cout<<i->second<<" ";
}
}
**ERROR : ** Time limit exceeding(That is the code doesn't stop running)
**NOTE** : Also, I found that I'm unable to update the `horizontal distance(hd)` properly in my code for every node. And I can't add `hd` as a member of Node class, so I have to fit it inside this function itself and I can't figure it out a way to do it.(`hdl` and `hdr`)
Please help and give some corrections to the code.
Thank you in advance.
There are two issues in your code. One is that you're only storing the node values in the queue instead of the node pointers. So your traversal condition
if(root->left)
is only checking for the children of the root node. This leads to an infinite loop because we are not traversing past the root node.
The second issue is even if we traversed correctly, the top view logic is not using the map correctly.
m[hd] = node_val
Since this is overwriting for each hd, this will give you the bottom view. We want the first occurence for each hd here. I have updated the code.
void topView(Node * root) {
queue<pair<Node*, int>> q;
map<int, int> m;
q.push({root->data, 0});
while(q.empty() == false){
Node* current_node = q.front().first;
int node_val = current_node->data;
int hd = q.front().second;
if(m.find(hd) == m.end())
m[hd] =node_val;
q.pop();
if(current_node->left){
int hdl = hd -1;
q.push({current_node->left, hdl});
}
if(current_node->right){
int hdr = hd + 1;
q.push({current_node->right, hdr});
}
}
for(auto i=m.begin();i!=m.end();i++)
{
cout<<i->second<<" ";
}
}

I am getting a TLE error while performing cycle detection

I have written a code to the leetcode problem(courseSchedule) which basically asks whether a given set of courses can be done given dependencies. my approach is to create a graph and then check for a cycle, however, it's giving a TLE error. Can you help me as to why is the TLE happening or if there's a better approach that I can use ?
bool cycle( vector<vector<int>> &adj,int i,vector<bool> vis){
if(vis[i])
return true;
vis[i]=true;
for(int k=0;k<adj[i].size();k++)
if(cycle(adj,adj[i][k],vis))
return true;
return false;
}
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> adj(numCourses);
for(int i=0;i<prerequisites.size();i++)
adj[prerequisites[i][1]].push_back(prerequisites[i][0]);
vector<bool> vis(numCourses,false);
for(int i=0;i<numCourses;i++)
if(cycle(adj,i,vis))
return false;
return true;
}
};
Actually, your function is correct but so inefficient.
This is because in the cycle function performs so many redundant operations i.e check for the same node multiple times.
Your Code:
bool cycle( vector<vector<int>> &adj,int i,vector<bool> vis){
if(vis[i])
return true;
vis[i] = true;
for(int k = 0; k < adj[i].size(); k++)
if(cycle(adj, adj[i][k], vis))
return true;
return false;
}
Ex:
0 ---> 1 ---> 2 ......... (some more edges)
0 ---> 3 ---> 2 ---> 4 ........ (some more edges)
So, for this graph, for the start vertex 0 (with your code) for the bool function:
iteration - 1: you perform the DFS and check for 1 and 2 and
......
iteration - 2: you perform the DFS and check for 3 and again 2 .....
So, like this, you will be recomputing the same sub-problems. To avoid this you need to put another array just check if a node is already computed.
So I have introduced another vector var (initialized to false) which basically sets to true if node is visited and got approved as non-cycle node (which doesn't involve in a cycle) .
Improved Code:
bool cycle( vector<vector<int>> &adj,int i,vector<bool> vis, vector<bool>& var){
// if i involves in cycle and visited in the current sequence
if(!var[i] and vis[i])
return true;
vis[i] = true;
for(int k=0;k<adj[i].size();k++) {
// if adj[i][k] is true i.e doesn't involve in cycle, so no need to check it. If it is false we should check it.
if(!var[adj[i][k]] and cycle(adj,adj[i][k],vis, var))
return true;
else
var[adj[i][k]] = true; // else setting true to tell it doesn't involve in cycle
}
// setting true to tell it doesn't involve in cycle
var[i] = true;
return false;
}
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> adj(numCourses);
for(int i=0;i<prerequisites.size();i++)
adj[prerequisites[i][1]].push_back(prerequisites[i][0]);
vector<bool> vis(numCourses,false);
vector<bool> var(numCourses,false);
for(int i=0;i<numCourses;i++)
if(cycle(adj,i,vis, var))
return false;
return true;
}
};
Note:
I just made small changes to make your code overcome TLE without changing the basic logic. But this is still inefficient as your logic needs to pass the vector by value. I suggest you think another way :)
I also think vis is not passed by reference would be the problem for large size test cases.
This is a similar depth first search graph method, that'd pass through:
#include <cstdint>
#include <utility>
#include <vector>
const static struct Solution {
static bool canFinish(
const int num_courses,
const std::vector<std::vector<int>>& prerequisites
) {
GraphType graph = buildCourseGraph(prerequisites, num_courses);
std::vector<bool> to_take(num_courses, false);
std::vector<bool> taken(num_courses, false);
for (SizeType course = 0; course < num_courses; ++course) {
if (!taken[course] && !validateAcyclic(graph, course, to_take, taken)) {
return false;
}
}
return true;
}
private:
using GraphType = std::vector<std::vector<int>>;
using SizeType = std::uint_fast16_t;
static GraphType buildCourseGraph(
const std::vector<std::vector<int>>& prerequisites,
const SizeType num_courses
) {
GraphType graph(num_courses);
for (const auto& prerequisite : prerequisites) {
graph[prerequisite[1]].emplace_back(prerequisite[0]);
}
return graph;
}
static bool validateAcyclic(
const GraphType& graph,
const SizeType& course,
std::vector<bool>& to_take,
std::vector<bool>& taken
) {
if (to_take[course]) {
return false;
}
if (taken[course]) {
return true;
}
to_take[course] = taken[course] = true;
for (const auto& adj_course : graph[course]) {
if (!validateAcyclic(graph, adj_course, to_take, taken)) {
return false;
}
}
to_take[course] = false;
return true;
}
};
and here is LeetCode's depth first search solution in Java (with comments):
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
// course -> list of next courses
HashMap<Integer, List<Integer>> courseDict = new HashMap<>();
// build the graph first
for (int[] relation : prerequisites) {
// relation[0] depends on relation[1]
if (courseDict.containsKey(relation[1])) {
courseDict.get(relation[1]).add(relation[0]);
} else {
List<Integer> nextCourses = new LinkedList<>();
nextCourses.add(relation[0]);
courseDict.put(relation[1], nextCourses);
}
}
boolean[] checked = new boolean[numCourses];
boolean[] path = new boolean[numCourses];
for (int currCourse = 0; currCourse < numCourses; ++currCourse) {
if (this.isCyclic(currCourse, courseDict, checked, path))
return false;
}
return true;
}
/*
* postorder DFS check that no cycle would be formed starting from currCourse
*/
protected boolean isCyclic(
Integer currCourse, HashMap<Integer, List<Integer>> courseDict,
boolean[] checked, boolean[] path) {
// bottom cases
if (checked[currCourse])
// this node has been checked, no cycle would be formed with this node.
return false;
if (path[currCourse])
// come across a previously visited node, i.e. detect the cycle
return true;
// no following courses, no loop.
if (!courseDict.containsKey(currCourse))
return false;
// before backtracking, mark the node in the path
path[currCourse] = true;
boolean ret = false;
// postorder DFS, to visit all its children first.
for (Integer child : courseDict.get(currCourse)) {
ret = this.isCyclic(child, courseDict, checked, path);
if (ret)
break;
}
// after the visits of children, we come back to process the node itself
// remove the node from the path
path[currCourse] = false;
// Now that we've visited the nodes in the downstream,
// we complete the check of this node.
checked[currCourse] = true;
return ret;
}
}
References
For additional details, please see the Discussion Board which you can find plenty of well-explained accepted solutions in there, with a variety of languages including efficient algorithms and asymptotic time/space complexity analysis1, 2.

Don't understand why I need a return on the last lines

I'm solving a problem about figuring out the minimum path to a leaf in a tree. I'm using BFS in C++ with a queue that stores a node and the current depth.
I traverse the tree in BFS adding nodes to my queue as I go along. As soon as I reach my first leaf I exit my cycle.
I don't understand why I need to add the return 0; line at the end of the program (commented on the code).
If I remove that line I get an error saying that the function got to the end without a return.
In which case will I need it?
class TreeDepth{
TreeNode* node;
int depth;
public:
TreeDepth(int depth, TreeNode* node): depth(depth), node(node) {}
TreeNode* getNode() {return node;}
int getDepth() {return depth;}
};
class Solution {
public:
int minDepth(TreeNode* root) {
if(!root)
return 0;
else
{
std::queue<TreeDepth> depthQ;
TreeDepth nodeDepth(1,root);
depthQ.push(nodeDepth);
while(!depthQ.empty())
{
TreeDepth currentNode = depthQ.front();
depthQ.pop();
if(!currentNode.getNode()->left && !currentNode.getNode()->right)
return currentNode.getDepth();
else
{
if(currentNode.getNode()->left)
{
TreeDepth leftNodeDepth(currentNode.getDepth() + 1, currentNode.getNode()->left);
depthQ.push(leftNodeDepth);
}
if(currentNode.getNode()->right)
{
TreeDepth rightNodeDepth(currentNode.getDepth() + 1, currentNode.getNode()->right);
depthQ.push(rightNodeDepth);
}
}
}
}
return 0; // why do I need this line?
}
};
Because you have paths in the function that exit but don't return a value. For instance, if depthQ IS empty, your code would exit without returning anything (but for that final 'return 0'). And you've declared your function to return an int. So all code paths must return some int.

How do I return a pointer to a node nested as the value of a map? (Access violation)

So I'm trying to create my own graph interpretation with a linked list;
Essentially, I want to create nodes linked to other nodes by n/e/s/w coordinates and every time I create a node, these nodes get added to a list I can check on later called 'Exists'(if it exists).
I reflect on the pair 'yx' coordinates of these nodes to confirm that. This is what my header looks like this:
class Graph {
private:
struct Area {
pair<int , int> yx;
Area *north;
Area *east;
Area *south;
Area *west;
};
Area *Start;
Area *Current;
map<pair<int, int>, Area*> Exists; //Need to get the stored Area from this map
public:
Graph();
void Create();
//Add_Node calls Connect_Nodes()
void Add_Node(Area before, int code, int symbol, int color, pair<int,int> yx, string title, string description, int coordinate);
//Connects nodes if the key is found in the map
Area* Connect_Nodes(pair<int, int> yx, int coordinate);
};
Here is the implementation, Add_Node() called first in void Create():
Add_Node(*Start, 00001, '.', 3, Start->yx, "Hallway", "Halls", 1);
Add_Node Calls the connection next:
void Graph::Add_Node(Area before, pair<int, int> yx, ... int coordinate){
Area *ptr = Connect_Nodes(yx, coordinate);
And the Connect method:
Graph::Area* Graph::Connect_Nodes(pair<int,int> yx, int coordinate) {
pair<int, int> temp;
switch (coordinate) {
case 1:
temp.first = ++yx.first;
temp.second = yx.second;
break;
....
}
map<pair<int, int>, Area*>::iterator it;
it = Exists.find(temp);
if (it != Exists.end())
return it->second;
else return nullptr;
}
I'm probably missing something important with my pointer implementations, I get the following error:
Exception thrown: read access violation.
std::_String_alloc<std::_String_base_types<char,std::allocator<char> > >::_Get_data(...) returned 0x14.
I can create the nodes just fine, however, in a Display() method, ptr iterates to the node, when I run ptr->title on the created node, I get the read access violation. What could be causing this error?
I hope I've documented this well enough to be understood.
Edit: Step through discovered the following in my un-posted Add_Node method:
void Graph::Add_Node(Area before, pair<int, int> yx, int coordinate){
bool passed = true;
Area *ptr = Connect_Nodes(yx, coordinate);
if (ptr != NULL) {
switch (coordinate) {
case 1:
before.north = ptr;
case 2:
before.east = ptr;
case 3:
before.south = ptr;
case 4:
before.west = ptr;
}
}
else {
do
{
Current = new Area;
Current_Code++;
Current->code = Current_Code;
switch (coordinate) {
case 1:
if (before.north == NULL)
{
Current->yx.first = ++before.yx.first;
Current->yx.second = before.yx.second;
Exists[Current->yx] = Current;
before.north = Current; // PROBLEM LINE
return;
}
When I replaced before.north in the above code with Start->north I was able to display everything just fine without any errors!
Start->north = Current;
However, since I used the before instance throughout the code it will need an adjustment to work.
The idea is that 'before' signifies an existing node that would connect to the node to be added.

Dequeue function not outputting proper values

There seems to be an issue with my dequeue function within a queue class that I have. My dequeue function which is part of the position class, is not returning the correct values that have been enqueued into the list.
The values that have been enqueued are which is a position object, are 2,1 and -1, but when I dequeue that object i get 2,506216, and -1; When I assign the *pos ponter to an object I am left with the default values;The enqueue function seems to be working correctly for when I check the ptr values they are correct.
//position constructor
front = back = &header;
struct Posnode
{
Position *pos;
Posnode *next;
};
class Position
private:
Posnode *front,*back,header;
void Position::dequeue(Position&p)
{
Posnode *ptr=front->next;
front->next = ptr->next;
p = *ptr->pos;
p.geta();//checking for values but am left with the default
if (back == ptr)
{
back = front;
}
delete ptr;
}
v
oid Position::enqueue(Position n) //assigning Position object to end of queue
{
Posnode *ptr = new Posnode;
ptr-> pos = &n;
back->next = ptr;
back = ptr;
return;
}
Position copy,intial(5);
copy = intial;
if (copy.ismovelegal(posmoves, r))
{
copy.makemove(posmoves, r);
if (intial.solved(copy))
{
cin.get();
}
else
{
p.enqueue(copy);
}
}
copy.free();//clearing object private memebers
}
intial.free();
p.dequeue(o);//copy that was previous enqued is not enqued
o.geta();
Just Check out the Implementation of Deque first and then try your own. If its some syntax or semantic error post minimal code that reproduces your code.
this link might help you. Deque Implementation