Ok I have to do a topological sorting algorithm on a graph. I need to find the node with in degree of 0 and queue it, then print it and remove all the edges going to it. I am removing the edges by decrementing the number of edges going into it in the countList map. I have the adjacency list as a map, and the count of in degrees for each node as a map. My algorithm is only accessing the first element of the adjacency list. so my output queue is only displaying the first key of the adjacency list map. over and over. I stopped the while loop at 25 so it wouldn't be infinite.
string z = "";
string a = "";
cout << "Queue: ";
do{
for(it = countList.begin(); it!=countList.end(); ++it){
if(it->second == 0){
Q.push(it->first);
countList.at(it->first)--;
z = adjList[it->first];
cout <<"z: " << z <<endl;
//remove edges
for(int i = 0; i< z.length(); i++){
a = z.at(i);
cout << "z at " <<i << " : " <<a <<endl;
countList.at(a)--;
}//end for
}//end if
//cout << Q.front() << ", ";
//Q.pop();
}//end for
cout << Q.front() << ", ";
Q.pop();
}while(!Q.empty());
Can someone help me with understanding why it is not iterating through the countList and is only staying on the first element?
Thank you.
So I changed the countList.at(a)-+1, to countList.at(a)-- for proper decrementation.
Now the output is more than just the first vertex that was 0 in degree. But the output is still wrong.
Here is the whole thing.
My variable declarations
vector<string> E;
map<string, string> adjList;
map<string, int>countList;
map<string, int>::iterator it;
queue<string> Q;
I don't want to put up the code for the adjacencyList or countList but here are how they look.
//These represent the edges between the two paired nodes
AdjacencyList: (1,2) (1,4) (1,3) (2,4) (2,5) (3,6) (4,6) (4,7) (4,3) (5,4) (5,7) (7,6)
//The first is the node name and the second element is how many edges come into that node.
countList: (1,0) (2,1) (3,2) (4,3) (5,1) (6,3) (7,2)
My output should be either:
Queue: 1,2,5,4,3,7,6
//or
Queue: 1,2,5,4,7,3,6
OK I added
countList.at(it->first)--;
after I push the vertex onto the queue. So that should decrement the count of that vertex to -1.
This narrowed my output alot.
OK IT WORKS NOW!!!
I changed the while loop to stop after the queue is empty and printed the queue in the while loop and it fixed the problem.
My output now is:
Queue: 1, 2, 5, 4, 7, 3, 6,
Ok this code will only work if the node names are only single values.
How would I change the adjList mapping for values that node names are longer than a single character?
Perhaps a linked list being pointed to by the key value? And if so how would I do that?
Ok, now we're getting somewhere.
The very first version (before your edit) did decrement the incoming edge count incorrectly.
Now there is another issue: In each iteration, you repeatedly take nodes that have already been taken (node #1 is a good example) because they still have zero count (number of incoming edges). By decrementing their ancestors again and again, some of the counts will drop below zero (such as for node #2).
You have to somehow mark the nodes that have already been used and do not use them again and again in each cycle. This can either be achieved a) by setting some flag for the node, b) using a set of used nodes, c) by removing the node from the list, or (probably the simpliest) d) by setting their edge count to a negative number (for instance, -1) after putting them into the output queue.
After your second edit, the algorithm as such should work (it works for me after some minor tweeks). However, the usage of adjList is pretty strange -- how do you exactly include multiple edges for one node into a map?
Related
I am working on the LeetCode problem 987: Vertical Order Traversal of a Binary Tree:
Given the root of a binary tree, calculate the vertical order traversal of the binary tree.
For each node at position (row, col), its left and right children will be at positions (row + 1, col - 1) and (row + 1, col + 1) respectively. The root of the tree is at (0, 0).
The vertical order traversal of a binary tree is a list of top-to-bottom orderings for each column index starting from the leftmost column and ending on the rightmost column. There may be multiple nodes in the same row and same column. In such a case, sort these nodes by their values.
Return the vertical order traversal of the binary tree.
This is my code:
class Solution {
public:
vector<vector<int>> verticalTraversal(TreeNode* root)
{
map<int, map<int, vector<int> > > nodes; // actual mapping
queue<pair<TreeNode*, pair<int, int> > > q; // for storing in queue along with HD and level no.
vector<vector<int>> ans;
vector<int> cur_vec;
if(!root){
return ans;
}
q.push(make_pair(root, make_pair(0, 0)));
while(!q.empty()){
pair<TreeNode*, pair<int, int> > temp = q.front(); // for storing the queue.front value in temp
q.pop();
TreeNode* frontNode = temp.first;
int hd = temp.second.first;
int level = temp.second.second;
nodes[hd][level].push_back(frontNode->val);
if(frontNode->left)
q.push(make_pair(frontNode->left, make_pair(hd-1, level+1)));
if(frontNode->right)
q.push(make_pair(frontNode->right, make_pair(hd+1, level+1)));
}
for(auto i: nodes){
for(auto j: i.second){
for(auto k: j.second){
cur_vec.push_back(k);
}
}
ans.push_back(cur_vec);
cur_vec.resize(0);
}
return ans;
}
};
I've used a multidimensional map in my answer which maps horizontal distance to levels. It works for several test cases, but it fails to pass the test case when two nodes overlap each other and the smaller one has to come first.
For instance, here the correct output for one vertical line is [1,5,6] but mine is [1,6,5] (the overlapping nodes are 6 and 5):
What should I change to make it work?
In your final loop, you can just add a call to sort on the inner vector (that corresponds to a certain horizontal distance and certain level). It is in that vector you could get overlapping nodes.
So:
for(auto i: nodes){
for(auto j: i.second){
sort(j.second.begin(), j.second.end()); // <-- added
for(auto k: j.second){
cur_vec.push_back(k);
}
}
ans.push_back(cur_vec);
cur_vec.resize(0);
}
i want to determine if a given graph has the structure i want. The structure i want is that if the given graph's tree's roots form a cycle then the output is true, else is false.
Here’s an example graph:
It has 3 trees and the roots 1,5,4 form a cycle.
Also this is an example that should not pass because it does not contain tree's which root's form a cycle:
How can I decide given the vertices which trees should i search?
This is the code so far, printing the adjacency list of a given graph.
#include <iostream>
#include <vector>
using namespace std;
void addEdge(vector<int> vec[], int u, int v)
{
vec[u].push_back(v);
}
void printGraph(vector<int> vec[], int j)
{
cout << "Graph's adjacent list: \n";
for (int v = 0; v < j; ++v)
{
if (vec[v].size() == 0) continue;
cout << "Head(" << v << ")";
for (auto x = vec[v].begin(); x != vec[v].end(); x++)
cout << " -> " << *x;
cout << "\n" ;
}
}
int main()
{
int V = 10;
vector<int> vec[V];
addEdge(vec, 6, 3);
addEdge(vec, 7, 1);
addEdge(vec, 8, 9);
addEdge(vec, 6, 4);
addEdge(vec, 5, 1);
addEdge(vec, 1, 9);
addEdge(vec, 2, 5);
addEdge(vec, 1, 4);
addEdge(vec, 5, 4);
printGraph(vec, V);
return 0;
}
Your question is how to tell whether a given graph
contains exactly one cycle,
where each node on the cycle is the root of a tree.
The good news is that, assuming your graph is connected, then if property (1) is true, then so is property (2)! To see why this is, imagine deleting any edge from that cycle. Now you have a connected graph with no cycles, which is a tree. That means that every node, not just the ones on the cycle, can then be thought of as the root.
The nice part about this is that there’s a really nice algorithm for determining whether a graph is connected and contains exactly one cycle. First, count the number of edges in the graph. If the graph is indeed connected and contains exactly one cycle, then the number of edges should be exactly equal to the number of nodes. (A tree has one more node than edge, and you’ve added in an edge). If that isn’t the case, then stop - the answer is no.
From there, you know you have the right number of nodes and edges. You just need to check whether the graph is connected, and you can do that with a DFS or BFS over the graph.
The nice part about this is that if you implement it correctly, the runtime will be O(n), where n is the number of nodes, independently of the number of edges. After all, if you see more than n edges, you can stop the search.
Hope this helps!
I was solving some question on graph. It requires to store weight for N Nodes(N<=50000). I cant use matrix to store weight of graph(as 50000x50000 can't be allocated). Do you know any other way? Thanks.
My preferred way of storing not too dense graphs is using adjacency lists.
The downside using adjacency lists is however that you can't directly check if node i is connected to node j. Instead you traverse all neighbors of node i (in which j would eventually show up if it is connected with node i). Also it's not practical to remove edges. I use it when doing breadth-first or depth-first searches on a graph, since one is only interested in the set of neighbors and not whether two specific nodes are connected.
In summary:
Takes only as much memory as you have edges (which is what you wanted) but at least as much memory as you have nodes.
Easy to traverse egdes for any node, i.e. always constant time per neighbor
To check whether two nodes i and j are connected you need to traverse the whole neighborhoodlist of node i or j. Which is bad if one node is connected to almost all other nodes and cheap if its connected to a few
Removing edges is also expensive for large neighborhoods (at worst linear time in the number of neighbors of a node) and cheap for small neighborhoods.
Inserting edges is very cheap (constant time)
To give you an example (first with all weights 1)
using Graph = std::vector<std::vector<int>>;
now you can create a graph with n nodes with:
Graph mygraph(n);
And if you want to connect node i and j just do
mygraph[i].push_back(j);
mygraph[j].push_back(i);
And to traverse all edges of some node, you can simply do
for (int neighbor : mygraph[i]) {
std::cout << i << " is connected with " << neighbor << std::endl;
}
And now for the harder problem with general weights:
using Graph = std::vector<std::vector<std::pair<int, double>>>;
Graph myWeightedgraph(n);
Now you can insert edges very easily
double weight = 123.32424;
myWeightedgraph[i].push_back({j, w});
myWeightedgraph[j].push_back({i, w});
And for traversal:
for (auto& neighbor : myWeightedgraph[i]) {
std::cout << i << " is connected with " << neighbor.first << " with weight " << neighbor.second << std::endl;
}
If two nodes can't have multiple edges between them:
First think of some system how to give each existing edge an unique number.
Eg. for N nodes and node numbers netween 0 and N-1, a edge between node A and node B could simply have A*N+B (eg. in an uint64_t variable)
Then make a std::map of edges, with the calculated number as key and the weight as value. Most operations there have logarithmic time, which is not as good than the 2D array but still good, and you need much less memory.
There are generally two ways to represent graphs. As you stated, the first one is to use an adjacency matrix. The pros are that you can easily see if two nodes i and j are connected. The downside is the space complexity (O(V²) where V is the number of vertices).
The other one is the adjacency list: for each vertex, you store an adjacency list that contains every edge coming out of that vertex. Obviously, the spatial complexity is O(V + E) where V is the number of vertices and E the number of edges.
Note that you can store the edges in adjacency maps instead of lists. Let's say you give each edge a unique integer key. If your graph is sparse, an std::unordered_map would fit well since collisions odds will be low. This grants you on average O(1) lookup and insertion complexity for a given edge.
If your graph can have a huge number of edges, then just use a regular std::map which relies on red black trees. You'll then have a logarithmic complexity for both inserting or looking up a node.
Here is some sample code:
struct Edge {
int weight;
int start, end;
}
struct Vertex {
int key;
std::unordered_map<int, Edge> adjacency_map;
}
struct Graph {
std::vector<Edge> edges;
}
You can't allocate an array with size of orders 10^9 as a static memory. You should be using malloc instead. Better still, you can use adjacency list to store the graph.
This question was asked to me in an interview:
lets say we have above binary tree,how can i produce an output like below
2 7 5 2 6 9 5 11 4
i answered like may be we can have a level count variable and print all the elements sequentially by checking the level count variable of each node.
probably i was wrong.
can anybody give anyidea as to how we can achieve that?
You need to do a breadth first traversal of the tree. Here it is described as follows:
Breadth-first traversal: Depth-first
is not the only way to go through the
elements of a tree. Another way is to
go through them level-by-level.
For example, each element exists at a
certain level (or depth) in the tree:
tree
----
j <-- level 0
/ \
f k <-- level 1
/ \ \
a h z <-- level 2
\
d <-- level 3
people like to number things starting
with 0.)
So, if we want to visit the elements
level-by-level (and left-to-right, as
usual), we would start at level 0 with
j, then go to level 1 for f and k,
then go to level 2 for a, h and z, and
finally go to level 3 for d.
This level-by-level traversal is
called a breadth-first traversal
because we explore the breadth, i.e.,
full width of the tree at a given
level, before going deeper.
The traversal in your question is called a level-order traversal and this is how it's done (very simple/clean code snippet I found).
You basically use a queue and the order of operations will look something like this:
enqueue F
dequeue F
enqueue B G
dequeue B
enqueue A D
dequeue G
enqueue I
dequeue A
dequeue D
enqueue C E
dequeue I
enqueue H
dequeue C
dequeue E
dequeue H
For this tree (straight from Wikipedia):
The term for that is level-order traversal. Wikipedia describes an algorithm for that using a queue:
levelorder(root)
q = empty queue
q.enqueue(root)
while not q.empty do
node := q.dequeue()
visit(node)
if node.left ≠ null
q.enqueue(node.left)
if node.right ≠ null
q.enqueue(node.right)
BFS:
std::queue<Node const *> q;
q.push(&root);
while (!q.empty()) {
Node const *n = q.front();
q.pop();
std::cout << n->data << std::endl;
if (n->left)
q.push(n->left);
if (n->right)
q.push(n->right);
}
Iterative deepening would also work and saves memory use, but at the expense of computing time.
If we are able to fetch the next element at same level, we are done. As per our prior knowledge, we can access these element using breadth first traversal.
Now only problem is how to check if we are at last element at any level. For this reason, we should be appending a delimiter (NULL in this case) to mark end of a level.
Algorithm:
1. Put root in queue.
2. Put NULL in queue.
3. While Queue is not empty
4. x = fetch first element from queue
5. If x is not NULL
6. x->rpeer <= top element of queue.
7. put left and right child of x in queue
8. else
9. if queue is not empty
10. put NULL in queue
11. end if
12. end while
13. return
#include <queue>
void print(tree* root)
{
queue<tree*> que;
if (!root)
return;
tree *tmp, *l, *r;
que.push(root);
que.push(NULL);
while( !que.empty() )
{
tmp = que.front();
que.pop();
if(tmp != NULL)
{
cout << tmp=>val; //print value
l = tmp->left;
r = tmp->right;
if(l) que.push(l);
if(r) que.push(r);
}
else
{
if (!que.empty())
que.push(NULL);
}
}
return;
}
I would use a collection, e.g. std::list, to store all elements of the currently printed level:
Collect pointers to all nodes in the current level in the container
Print the nodes listed in the container
Make a new container, add the subnodes of all nodes in the container
Overwrite the old container with the new container
repeat until container is empty
as an example of what you can do at an interview if you don't remember/don't know the "official" algorithm, my first idea was - traverse the tree in the regular pre-order dragging a level counter along, maintaining a vector of linked-lists of pointers to nodes per level, e.g.
levels[level].push_back(&node);
and in the end print the list of each level.
I've just implemented a threaded tree in C++, and now I'm trying to cout all the elements in order.
The tree was a binary sorted tree (not balanced) before I've threaded it.
I've tried doing this:
E min = _min(root); //returns the minimum element of the tree
E max = _max(root); //returns the maximum element of the tree
while (min != max)
{
std::cout << min << ", ";
min = _successor(root, min);
}
std::cout << max << ", ";
std::cout << std::endl;
but since the tree is now threaded, my successor function always returns the minimum of the whole tree (basically, it goes once in the right subtree, and then goes in the left subtree as many times as possible, until it finds a leaf.) So when I try to call this function, it only cout 1's (because 1 is the minimum value of my tree).
Also, I've tried something else:
E min = _min(root); //returns min element of the tree
E max = _max(root); //returns max element of the tree
Node* tmp = _getNode(root, min); //returns the node of the specified element, therefore the minimum node of the tree
while(tmp->data < max)
{
std::cout << tmp->data << ", ";
tmp = _getNode(root, tmp->data)->rightChild; //gets the right child node of tmp
}
std::cout << tmp->data << ", ";
However, by doing this, there are values that are ignored. (See image below)
(Green links have been added after the threading of the tree.)
If you see, for example, the node #6 never gets visited from the very last algorithm, because it's not the right child of any node in the tree...
Here's the output of the previous function:
1, 2, 3, 5, 7, 8, 11, 71
Does anyone have an idea of how I could fix this, or any tips for my problem?
Thanks
EDIT: After all I just had to traverse the tree from the minimum to the maximum AND modify my _predecessor and _successor methods, so they wouldn't check in subtrees that are threaded. :)
Hope it helps future readers.
Try
Node* n = _min(root);
while (n->right) {
cout << n->val << ", ";
n = _successor(n);
}
cout << n->val << endl;
This is basically your first code (note that I assume that the tree is non-empty as do you). This also won't give you a trailing ','.
The important thing is to get your successor function correct. It should be like this
Node* _successor(Node* n) {
if (is_thread(o, RIGHT)) return o->right;
return _min(o->right);
}
And for completeness
Node* _min(Node* n) {
while (!is_thread(o, LEFT)) n = o->left;
return n;
}
For both of these all the green arrows are threads.
I've never seen threaded trees before, but I'll take a stab at this anyway. To build an inorder traversal, you could approach the root of the tree from two directions at once:
Start at the root.
Follow all left links until you find one that points to null. That element is the tree's minimum value.
Follow all right links until you reach the root. If you've built the tree correctly, this should traverse every element in increasing order.
Repeat steps 2 and 3 in the opposite direction (find the max element, walk backwards).
Join these two lists with the root in the middle.
That's probably not the fastest algorithm but I think it'll produce a correct answer. And you didn't have to use recursion, which I guess is the whole point for using a threaded tree.
After all I just had to traverse the tree from the minimum to the maximum
AND
modify my _predecessor and _successor methods, so they wouldn't check in subtrees that are threaded. :)
Hope it helps future readers.