I'm trying to solve the problem of Vertical Order Traversal of Binary Tree using map and queue. I did solve it using a recursive way, but I'm not getting the same answer using the iterative way.
10
/ \
7 4
/ \ / \
3 11 14 6
Approach :
First I declared an integer that stores horizontal distance from the root node.
Horizontal distance means that the left part from the root will be considered as -1, -2 and so on, like a negative X axis, where the root is origin and starts from 0. So node 7 will be given -1, 3 will be given -2. However, 10, 11, 14 will be given 0 as they are not away from root node but lie in the same position. And towards the right, distance will become positive so 4 will get distance 1, 6 will get 2 and so on.
At first, I pushed the root in the queue and updated the horizontal distance as 0. After that, I added horizontal distance as key and root data as value in the map. And finally, I poped the root from the queue and I checked for its left and right child, if left or right child was available, I pushed the left and right child in the queue respectively and updated horizontal distance accordingly. Then I followed the same procedure for the complete binary tree.
And then, I just traversed through the second part of the map to get the answer.
The Answer should be :
3
7
10 11 14
4
6
The Answer I received is :
10 7 4 3 11 14 6
Here is my Code :
#include <iostream>
#include <map>
#include <queue>
#include <vector>
using namespace std;
struct Node
{
int data;
Node *left;
Node *right;
Node(int val)
{
data = val;
left = NULL;
right = NULL;
}
};
map<int, vector<int>> verticalPrint(Node *root)
{
queue<Node *> qi;
map<int, vector<int>> mp;
int Hd = 0;
qi.push(root);
while (!qi.empty())
{
Node *temp = qi.front();
mp[Hd].push_back(temp->data);
qi.pop();
if (temp->left != NULL)
{
qi.push(temp->left);
Hd -= 1;
}
if (temp->right != NULL)
{
qi.push(temp->right);
Hd += 1;
}
}
return mp;
}
int main()
{
Node *root = new Node(10);
root->left = new Node(7);
root->right = new Node(4);
root->left->left = new Node(3);
root->left->right = new Node(11);
root->right->left = new Node(14);
root->right->right = new Node(6);
map<int, vector<int>> mp = verticalPrint(root);
map<int, vector<int>>::iterator it;
for (it = mp.begin(); it != mp.end(); it++)
{
for (int i = 0; i < it->second.size(); i++)
{
cout << it->second[i] << " ";
}
cout << endl;
}
return 0;
}
You cannot use a single Hd variable like that. Note how in the first iteration, Hd will go to -1 and back to 0 because the root has both a left and right child. So in the next iteration you start again with 0, yet the node that you pull from the queue has nothing to do with that value of Hd.
Instead, put pairs in the queue: a combination of node and its corresponding horizontal distance. Then it will work fine:
map<int, vector<int>> verticalPrint(Node *root)
{
queue<pair<int, Node *>> qi;
map<int, vector<int>> mp;
qi.push({0, root});
while (!qi.empty())
{
pair<int, Node*> item = qi.front();
int hd = item.first;
Node * temp = item.second;
mp[hd].push_back(temp->data);
qi.pop();
if (temp->left != NULL)
{
qi.push({hd - 1, temp->left});
}
if (temp->right != NULL)
{
qi.push({ hd+1, temp->right});
}
}
return mp;
}
Related
To find set of all nodes that are visible from left side of binary tree.
vector<int> getLeftView(TreeNode<int> *root)
{
static vector<int> res;
// Your code here
if(root){
res.push_back(root->data);
if(root->left)
getLeftView(root->left);
else
getLeftView(root->right);
}
return res;
}
For a single test case at a time it works fine. But when multiple test cases are run, the previous values in the vector is appended by the new values. How do I clear the vector before running the next test case?
You used static because you need a single instance of the vector to be used across the recursion. But static is not the way; it causes there to be just one instance of the vector in the entire program as such.
There are various solutions, one of which is to split the function into the API and recursive part:
void getLeftViewRec(TreeNode<int> *root, vector<int> &res)
{
if(root){
res.push_back(root->data);
if(root->left)
getLeftView(root->left, res);
else
getLeftView(root->right, res);
}
return res;
}
vector<int> getLeftView(TreeNode<int> *root)
{
vector<int> res;
getLeftViewRec(root, res);
return res;
}
Now what happens is that every time getLeftView is called, a new vector res is instantiated as a local variable. It then calls the recursive function getLeftViewRec which receives res by reference, and passes it to itself through the recursive calls, so the recursion is working with a single vector, accumulating into it.
Using queue and a null pointer to mark the first element of each level. we insert a null pointer in the first and as reach that null pointer we mark bool as true and take the next element as our left view element,
// C++ Code for the above iterative approach
#include <bits/stdc++.h>
using namespace std;
// Tree Node Structure contains data, left and right
// pointer
struct Node {
int data;
struct Node *left, *right;
};
// A utility function to
// create a new Binary Tree Node
struct Node* newNode(int item)
{
struct Node* temp
= (struct Node*)malloc(sizeof(struct Node));
temp->data = item;
temp->left = temp->right = NULL;
return temp;
}
// function to get the left view of binary tree in vector
vector<int> leftView(Node* root)
{
// store the left view
vector<int> ans;
// Base Case : Empty Tree
if (!root)
return ans;
// Create an empty queue and enque root node and null
queue<Node*> q;
q.push(root);
q.push(NULL);
bool ok = true;
// Traverse till queue is not empty
while (!q.empty()) {
// get the front node and dequeue it from queue
auto it = q.front();
q.pop();
// if the front node is null do following steps
if (it == NULL) {
if (ok == false)
ok = true;
if (q.size() == 0)
break;
else
q.push(NULL);
}
// else do the following steps
else {
if (ok) {
ans.push_back(it->data);
ok = false;
}
if (it->left)
q.push(it->left);
if (it->right)
q.push(it->right);
}
}
// return the left view
return ans;
}
// driver code to test above code on a test case
int main()
{
/*
Input :
10
/ \
2 3
/ \ / \
7 8 12 15
/
14
Output : 10 2 7 14
*/
// let's build above shown tree
Node* root = newNode(10);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(7);
root->left->right = newNode(8);
root->right->right = newNode(15);
root->right->left = newNode(12);
root->right->right->left = newNode(14);
// call leftview function and store output in vec
vector<int> vec = leftView(root);
// traverse on left view and print each element
for (int x : vec)
cout << x << " ";
cout << endl;
return 0;
}
There are total of 7 spaces, 3 leftmost spaces contain a frog each of one family
while the 3 rightmost spaces contain a frog each of second family. The 3 frogs
on left need to be transferred to 3 rightmost positions while 3 frogs on right need
to be transferred to 3 leftmost positions, but the condition is that each and every
one of the frog can jump either to next position in left or right of it (if empty)
or to two places to left or right (if empty).
Find a suitable set of instructions to get to final position
Initial State(Input):
FROG1 FROG1 FROG1 ___ FROG2 FROG2 FROG2
Final State(Output):
FROG2 FROG2 FROG2 ___ FROG1 FROG1 FROG1
(where FROG1 denotes frog of first family and FROG2 denotes frog of second family)
I don't know where is it going wrong but after running the code, it shows a warning in swap function that s[index] may be uninitialized. The output is blank whereas expected output should be the steps how the frogs crossed.
My Idea to solve:
The root of this tree is initial state, lets denote the state at one time by
"x" to denote frog of 1st family, "o" to denote frog of other family, "-" to denote space.
So, the initial state becomes: ooo_xxx and final state is xxx_ooo
The root node contains xxx_ooo, and information of its 4 children and its parent.
To generate children of a node, just move the space ("-") to left, right, left to left and
right to right of its position in parent node, if the state allows, otherwise the child
will be null.
Keep building the tree until the goal state is found and once the goal state is found
print the path in reverse order from that node to root using the pointer of its parent
Approach:
#include <bits/stdc++.h>
using namespace std;
const string finalState = "xxx_ooo";
const string initialState = "ooo_xxx";
struct tree {
string s;
struct tree *one, *two, *three, *four;
struct tree *parent;
};
struct tree *newNode(string str) {
struct tree *node;
node = (struct tree*) malloc(sizeof(struct tree));
node->s = str;
node->one = nullptr;
node->two = nullptr;
node->three = nullptr;
node->four = nullptr;
return node;
}
void display(struct tree *node) {
struct tree * par = node->parent;
while(node->parent != nullptr) {
cout << node->s << endl;
node = par;
par = node->parent;
}
}
string nextState(string s, int choice) {
int index;
for(int i = 0; i < static_cast<int>(s.size()); i++) {
if(s[i] == '_') {
index = i;
}
}
if(index + choice >= 0 && index + choice < 7)
swap(s[index], s[index + choice]);
return s;
}
void insertUpdated(struct tree *curr, string str, int num) {
switch(num) {
case 1: curr->one = newNode(str);
curr->one->parent = curr;
break;
case 2: curr->two = newNode(str);
curr->two->parent = curr;
break;
case 3: curr->three = newNode(str);
curr->three->parent = curr;
break;
case 4: curr->four = newNode(str);
curr->four->parent = curr;
break;
}
}
void generateChild(struct tree *root) {
queue<struct tree*> q;
struct tree* ans;
q.push(root);
int cnt = 0;
while(true) {
struct tree *temp = q.front();
q.pop();
cnt++;
if(temp->s == finalState){
ans = temp;
break;
}
string s1, s2, s3, s4, curr = temp->s;
s1 = nextState(curr,-2);
s2 = nextState(curr,-1);
s3 = nextState(curr,1);
s4 = nextState(curr,2);
insertUpdated(temp, s1, 1);
insertUpdated(temp, s2, 2);
insertUpdated(temp, s3, 3);
insertUpdated(temp, s4, 4);
q.push(temp->one);
q.push(temp->two);
q.push(temp->three);
q.push(temp->four);
}
display(ans);
}
int main() {
struct tree *root = newNode(initialState);
generateChild(root);
return 0;
}
I have a while loop which continuously takes integers until -1 is entered. Those elements must be inserted into a binary tree (not a BST). If it was a BST, we have a condition for where to insert the new node. But how can I construct a binary tree?
I mean if nodes are 1,2,3,4,5,6..., then
1 is the root, 2 and 3 are the left and right children of node 1,
4 and 5 are the left and right children of node 2, and 6 is left child of node 3, like this:
if(root==NULL)
root= newnode;
else{
if (root->left==NULL)
root->left= insert(root->left,element);
else
root->right= insert(root->right,element);
}
return root;
How do I create a tree like this?
One simple way of doing this is use level order traversal.
Whenever you find a node whose left or right child is NULL, attach the new node as a child of that node; if both left and right are NULL, attach as left child, else attach as right child.
tree_node *insert_node_in_tree(tree_node *root, node new_node) {
if(root == NULL)
return new_node;
queue <tree_node * > qu;
tree_node *temp;
qu.push(root);
while(!(qu.empty())) {
temp = qu.front();
qu.pop();
if(temp->left == NULL || temp->right == NULL)
break;
qu.push(temp->left);
qu.push(temp->right);
}
if(temp->left == NULL)
temp->left = new_node;
else
temp->right = new_node;
return root;
}
The algorithm outlined by WhozCraig in his comment can be realized by the code:
/* Create a binary tree with nodes presented in BFS order */
#include <cassert>
#include <iostream>
#include <vector>
#include <iomanip>
using std::vector;
using std::cout;
using std::cin;
using std::ostream;
using std::setw;
struct node
{
int data;
node *left;
node *right;
node(int n) : data(n), left(0), right(0) { }
};
void print_bt(const node *root);
int main()
{
vector<node> v;
int n;
// Read data to EOF or a negative value
while (cin >> n && n >= 0)
v.push_back(node(n));
// Create binary tree
for (size_t i = 0; i < v.size()/2; i++)
{
assert(2*i+1 < v.size());
v[i].left = &v[2*i+1];
if (2*i+2 < v.size())
v[i].right = &v[2*i+2];
}
// Print binary tree
print_bt(&v[0]);
return 0;
}
// print_bt() presents the data so that if you mentally rotate the
// output through 90º clockwise (so the root is at the top), then the
// left child appears on the left and the right on the right. Reversing
// the order of left/right leaves that as somewhat confusing.
void print_bt(const node *root)
{
static int level = 0;
if (root != nullptr)
{
level++;
print_bt(root->right);
cout << setw(4*level) << root->data << '\n';
print_bt(root->left);
level--;
}
}
For example, given the numbers 1 to 6 as input, it produces:
3
6
1
5
2
4
and given the numbers 1 to 15 as input, it produces:
15
7
14
3
13
6
12
1
11
5
10
2
9
4
8
It helps if you visualize the tree rotated 90º clockwise, so that the 1 is at the top.
After extensive testing and debugging, I cannot for the life of my find out why my topological sort algorithm produces the incorrect output. It simply lists the values of the nodes in descending order instead of sorting them topologically. I have listed all relevant classes/input files. Any hints or help is appreciated, thanks in advance.
Header for class graph:
/*
2/19/2016
This is the header for class graph. It includes the definition of a node
and the function signatures
*/
#pragma once
#include <iostream>
using namespace std;
struct node
{
// actual value at each node
int value;
// discovered time
int d;
// finished time
int f;
// keep track of how many edges each vertex has
int numEdges;
// keep track of color of node
char color;
// parent (previous) node
node* p;
// next node
node* next;
};
// Class to represent a graph
class Graph
{
public:
// constructor, give number of vertexes
Graph(int V);
// depth first search
void DFS();
// function to print sorted nodes
void print();
// function for reading file into adjacency list
void readFile(istream& in);
private:
// private function called in depth first search, visits every vertex
// of each edge in the graph
void DFSVisit(node* u);
// number of vertices
int V;
// array of node pointers, first node in each array is
// the vertex and following nodes are edges
node* adj[9];
// linked list to keep track of the sorted list found from depth first search
node* sorted;
// keep track of when each node is discovered/finished
int time;
// keep track of number of backedges
int backEdge;
};
The cpp file for class graph
/*
2/19/2016
This is the cpp file for class graph. It defines function behavior
*/
#include "Graph.h"
using namespace std;
#include <iostream>
#include <string>
Graph::Graph(int V)
{
// set graph's number of vertexes to number input
this->V = V;
this->backEdge = 0;
}
// Depth first search
void Graph::DFS()
{
// initialize all colors to white and parent to null
for (int i = 0; i < V; i++)
{
adj[i]->color = 'w';
adj[i]->p = NULL;
}
// initialize time to 0
time = 0;
// for each vertex, if it is white, visit its adjacent nodes
for (int i = 0; i < V; i++)
{
if (adj[i]->color == 'w') {
DFSVisit(adj[i]);
}
}
}
// Visit node used by depth first search
void Graph::DFSVisit(node* u)
{
// increment time
time++;
// set u's discovered time
u->d = time;
// set color to grey for visited but not finished
u->color = 'g';
// visit each adjacency, number of adjacencies stored by numEdges
for (int i = 0; i < u->numEdges; i++)
{
// create node pointing at u next
node* v = u->next;
// if the node is already grey, then it is a backedge
if (v->color == 'g') {
backEdge++;
}
// if it is white and undiscovered, set its parent to u and visit v's next nodes
else if (v->color == 'w') {
v->p = u;
DFSVisit(v);
}
}
// set last node to black
u->color = 'b';
// increment time
time++;
// set finishing time
u->f = time;
if (backEdge == 0) {
// adds a node to front of linked list that contains sorted values
node* newNode = new node;
newNode->next = sorted;
newNode->value = u->value;
sorted = newNode;
}
}
void Graph::print()
{
if (backEdge == 0) {
node* curr = sorted;
if (sorted == NULL) {
return;
}
else {
cout << "Sorted List:\n";
for (; curr; curr = curr->next)
{
cout << curr->value << " ";
}
cout << endl;
}
}
else cout << "Backedges: " << backEdge << endl;
}
void Graph::readFile(istream& in)
{
// create node pointers to use later
node* head;
node* prev;
node* curr;
// temp string to use while reading file
string temp;
int j;
// loop iterate vertex number of times
for (int i = 0; i < V; i++)
{
// 3rd character in string holds name of first edge
j = 3;
// read line by line
getline(in, temp);
// debug print out adjacency list
// cout << temp << endl;
// create head node, set value to value of vertex, put it at beginning of each linked list
head = new node;
head->value = i + 1;
adj[i] = head;
// set numEdges to 0 when row is started
adj[i]->numEdges = 0;
// set prev to head at end of each outer loop
prev = head;
// read every adjacency for each vertex, once j goes outside of string reading is done
while (j < temp.length()) {
// increment numEdges, meaning vertex has one more adjacency
adj[i]->numEdges++;
// create node and put in value, found by moving j up two spaces and subtracting 48
// because it is a char casted as an int
curr = new node;
curr->value = (int)temp.at(j) - 48;
// connect node, increment j by 2 because adjacencies separated by a whitespace
prev->next = curr;
prev = curr;
j += 2;
}
}
}
The driver for the program
/*
2/19/2016
This is the driver for the topological sort project. It reads a file of
vertexes and edges into an adjacency list and performs a depth first
search on that graph representation, creating a topological sort
if no backedges exist, this indicates a DAG or directed acyclic graph
if backedges do exist, this indicates a graph containing cycles meaning
it cannot be topologically sorted
*/
#include <iostream>
#include <fstream>
#include <string>
#include "Graph.h"
using namespace std;
string FILE_NAME = "graphin-DAG.txt";
int NUM_VERTICES = 9;
int main()
{
// create graph object giving number of vertices
Graph myGraph(NUM_VERTICES);
// open file
ifstream fin(FILE_NAME);
// validate that file was successfully opened, without file print
// error and exit program
if (!fin.is_open()) {
cerr << "Error opening " + FILE_NAME + " for reading." << endl;
exit(1);
}
// read file into adjacency list
myGraph.readFile(fin);
// perform depth first search
myGraph.DFS();
// if graph is a DAG, print topological sort, else print backedges
// this is handled by the print function checking backedges data member
myGraph.print();
}
And the input file
1: 2
2: 3 8
3: 4
4: 5
5: 9
6: 4 7
7: 3 8
8: 9
9:
Also a visual representation of the graph represented by the adjacency list:
http://i.imgur.com/6fEjlDY.png
I think the main problem was that there was some confusion between the 'real' nodes and the nodes in your adjacency list. At least I got confused, so I split the structure into struct Node and struct Adj. The graph now has a Node* nodes[9] for the nodes.
struct Node;
struct Adj
{
Node* node;
Adj* next;
};
struct Node
{
// actual value at each node
int value;
// discovered time
int d;
// finished time
int f;
// keep track of color of node
char color;
// the list od adjacencies for the node
Adj* adj;
};
and things almost instantly seem to work. The answer
Sorted List:
6 7 3 4 5 1 2 8 9
seems correct, [6 7 3 4 5] and [1 2 8 9]. See working example here
Please note that there are still numerous issues with the code, esp. with regard to memory management. Consider using a vector<Node> and a std::vector<Adj>. There are also uninitialized variables in the structs.
First of all ,I am new to graphs.After researching through the concepts of graphs.I thought of implementing in c++. When I searched for implementation i felt it very hard to understand the codes ,So i thought of implementing myself.
Following is the code i tried:
#include<iostream>
using namespace std;
struct Node {
int data;
Node *link;
};
//creating array of nodes
struct Node *array[10];
//creating array of head pointers to point each of the array node.
struct Node *head[10];
//creating array of current pointers to track the list on each array node.
struct Node *cur[10];
void create(int v)
{
for (int i = 0; i < v; i++) {
array[i] = new Node;
head[i] = cur[i] = array[i];
array[i]->data = i;
array[i]->link = NULL;
}
}
void add(int fr, int to)
{
Node *np = new Node;
np->data = to;
np->link = NULL;
if (head[fr]->link == NULL) {
head[fr]->link = np;
cur[fr] = np;
} else {
cur[fr]->link = np;
cur[fr] = np;
}
/*Node* np1=new Node;
np1->data=fr;
np1->link=NULL;
if(head[to]->link==NULL)
{
head[to]->link=np1;
cur[to]=np1;
}else
{
cur[to]->link=np1;
cur[to]=np1;
}*/
}
void print(int a)
{
Node *p = NULL;
p = head[a];
for (; p != NULL; p = p->link)
{ cout << p->data; }
}
main()
{
int a;
cout << "enter the size of array";
cin >> a;
create(a);
//adding edges
add(1, 4);
add(1, 3);
add(0, 3);
add(0, 2);
print(0);
cout << "\n";
print(1);
//print(3);
}
Explanation:
1) Asking the user to enter an integer(no.of vertices),accordingly i am creating an array with requested size.At the same time i am pointing the head and cur pointers to each of the array node. The index number of the array is equal to vertex number.
2)adding edges from one vertex to other by add function. if the head node of a vertex from which an edge emanates is null then i point the head=cur=new node(np),else i am updating cur pointer after each addition. Head will be pointing to the array index node.
3)Printing the edges connected to the requested node.
My questions are:
1)Is this way of implementation right?
2)In the above case lets assume we are connecting vertex 1 and vertex 3.with the above code3 is linked to 1.I wanted to automatically update connection from vertex 3 to vertex 1,So i added the code which is inside the comment section in add function.When i tried running the code it asked me to enter size of array ,i enter some integer it shows me segmentation fault. why?
I'll try to give you the idea.
In an undirected graph every node can be connected to any other node.
This means a node 'points' to any number of other nodes.
In you code instead each node has Node*link; which is a pointer to the next node. You need a list (or an array) of links instead: each node must contain a link to all the node it is connected to. This is the adjacency list. Something like
struct Node
{
int data;
ADJ* adjs; // list of Node*
};
struct ADJ
{
ADJ* next;
Node* data;
};
Here adjs is the list of adjacency.
Also your solution for void print(int a) is more similar to what you would find in a common list. You need to print all the adjacency of a node, i.e. all the node it points to.
Remember that since the graph is undirected you need both the pointert A->B and B->A
After calling create(3) your array looks something like below:
array
0 -> (0,NULL)
1 -> (1,NULL)
2 -> (2,NULL)
3
4
5
6
7
8
9
Segmentation fault occured when add(1,4) is called.
In the first part i.e.
Node *np = new Node;
np->data = to;
np->link = NULL;
if (head[fr]->link == NULL) {
head[fr]->link = np;
cur[fr] = np;
} else {
cur[fr]->link = np;
cur[fr] = np;
}
no problem at all.
Now array looks as shown:
array
0 -> (0,NULL)
1 -> (1,->) (4,NULL)
2 -> (2,NULL)
3
4
5
6
7
8
9
But the Next part is the cause of segmentation fault i.e.
Node* np1=new Node;
np1->data=fr;
np1->link=NULL;
if(head[to]->link==NULL)
{
head[to]->link=np1;
cur[to]=np1;
}else
{
cur[to]->link=np1;
cur[to]=np1;
}
problem is in this line:
head[to]->link==NULL
Here value of to is 4 it means your code trying access link part of head[4] but head[4] is not storing address of valid Node.