I need some working snippets on C++ code regarding breadth/depth first searches. Also, in the links below, when using the term tree, is it in reference to a binary tree or more specefically a red and black tree? Or is this a more abstract tree of sorts? Does anyone have a link to working code for these searches...along with constructing the tree?
Tree seems to refer to some sort of constuct with in the "graph"? I believe this is some sort of math I have not taken yet.
breadth or depth first search 1
breadth or depth first search 2
The tree in question is the thing they're searching. It's kinda hard to understand search algorithms without knowing what it is they are searching through.
A tree is a type of graph. A graph is a series of nodes (which presumably represent some data) with connections between certain nodes. A tree is a graph where the connections between nodes form a hierarchy. For any given node in the graph, it has exactly one "parent" that points to it, and it points to zero or more child nodes. And the nodes cannot form circles; a parent cannot point to a child who points to that parent.
Basically, like branches on a tree.
The term "tree" refers to any data structure that can be abstractly looked at as a tree.
A "tree" is a data structure in which there are parent nodes and child nodes, and each child has a single parent, with a single "root" node not having a parent.
If a node in your tree has multiple parents, it is called a "graph".
A tree is a special case of a directed acyclic graph (basically a bunch of 'nodes' with arrows ('edges') pointing at each other, such that there cannot be a loop of arrows) in which the following two conditions hold:
No node has more than one incoming edge
There exists a single distinguished node (the 'root') from which all other nodes are reachable.
The nodes reachable via an outgoing edge from some node N are often called N's children.
Breadth-first and depth-first search apply to generic trees (indeed, they apply to all DAGs). However there are some more specific types:
Binary trees are trees in which no node has more than two outgoing edges; outgoing edges are labelled, usually as 'left' and 'right'
Search trees are binary trees in which each node has a key; further, the key in some node N is greater than the child on its left edge (if any) and less than the child on its right edge (if any). This allows for very fast searching for a specific key.
Red-black trees are a specific kind of search tree in which a moderately complex algorithm is used to make sure all keys are approximately the same distance from the root.
Related
Sorry in advance, this a very specific question and I cannot provide any piece of code as this is for my job, thus confidential.
I am using the Boost R-trees, and an algorithm that I need to implement requires to access the non leaf nodes of the tree. With Boost rtree library, I only can access leaf nodes in an easy way. I noticed that there is a function to print all the nodes including the non leaf nodes (which means they exist, they are computed), with their position, their level in the tree etc, but I cannot access them the same way than the leaf nodes.
For now, the best solution that I have is to implement a visitor for the tree and overload the operator () to gather the nodes (this is what the print method does to access the nodes).
My question is, does anybody know an easier way to access the non leaf nodes ? Because this one does not seem to be efficient, and I'm loosing time each time I want to access a non leaf node. Moreover, I need to replicate the structure of the tree without the points, and I cannot do that if I cannot access the non leaf nodes.
Thank you in advance !
I don't know what would you like to do exactly so this will be a general answer.
In order to access the tree nodes for the first time you have to traverse the tree structure. In Boost.Geometry rtree visitor pattern is used for that. You could do it manually but internally Boost.Variant is used to represent the nodes so you'll end up with variant visitor instead. At this point you have a few options depending what are you going to do with the nodes. Are you going to modify the r-tree? Will the rtree be moved in memory? Will the addresses of nodes change? How many nodes are you going to access? Do you want to store some kind of reference to a node and traverse the tree structure from that point? Do you want to traverse the structure downward or upward?
One option as you noticed is to traverse the tree structure each time. This is a good approach if the tree structure can change. The obvious drawback is that you have to check all child nodes at each node using some condition (whatever you do in order to pick the node of interest).
If the tree structure does not change but the tree is copied to a different place in memory you can represent the node as a path from the root to the node of interest as list of indexes of child nodes. E.g. a list {1, 2, 3} meaning: traverse the tree using child node 1 of root node, then at the next level pick child node 2, then your node will be child node 3 at the next level. In this case you still have to traverse the tree but doesn't have to check conditions again.
If the tree does not change and nodes stays in the same place in memory you can simply use pointers or references.
I have a DAG-like structure that is essentially a deeply-nested map. The maps in this structure can have common values, so the overall structure is not a tree but a direct acyclic graph. I'll refer to this structure as a DAG for brevity.
The nodes in this graph are of different but finite number of categories. Each category can have its own structure/keywords/number-of-children. There is one unique node that is the source of this DAG, meaning from this node we can reach all nodes in the DAG.
The task is to traverse through the DAG from the source node, and convert each node to another one or more nodes in a new constructed graph. I'll give an example for illustration.
The graph in the upper half is the input one. The lower half is the one after transformation. For simplicity, the transformation is only done on node A where it is split into node 1 and A1. The children of node A are also reallocated.
What I have tried (or in mind):
Write a function to convert one object for different types. Inside this function, recursively call itself to convert each of its children. This method suffers from the problem that data are immutable. The nodes in the transformed graph cannot be changed randomly to add children. To overcome this, I need to wrap every node in a ref/atom/agent.
Do a topological sort on the original graph. Then convert the nodes in the reversed order, i.e., bottom-up. This method requires a extra traverse of the graph but at least the data need not to be mutable. Regarding the topological sort algorithm, I'm considering DFS-based method as stated in the wiki page, which does not require the knowledge of the full graph nor a node's parents.
My question is:
Is there any other approaches you might consider, possibly more elegant/efficient/idiomatic?
I'm more in favour of the second method, is there any flaws or potential problems?
Thanks!
EDIT: On a second thought, a topological sorting is not necessary. The transformation can be done in the post-order traversal already.
This looks like a perfect application of Zippers. They have all the capabilities you described as needed and can produce the edited 'new' DAG. There are also a number of libraries that ease the search and replace capability using predicate threads.
I've used zippers when working with OWL ontologies defined in nested vector or map trees.
Another option would be to take a look at Walkers although I've found these a bit more tedious to use.
I have given below assignment by my teacher to implement but I am not sure what can be effective approach to implement the same. I will appreciate if somebody share pointers to proceed further.
Problem description:
Assume a tree object having a depth of "n" (n is a known number). For the sake of simplicity, it can be assumed that each node in the tree is a simple string. The number of siblings and children for each node and at each level could be a variable number. It can also be assumed that there will be an API which can return us the number of children for each node (A dummy API can be used which returns a random whole number for this exercise). Also, each parent node has a node number range associated with it. The children of that parent will have node numbers which fall in the parent range. In effect:
1. Each node will have a range (whole number) to identify its children
2. Each node will also have a unique node number to identify itself
With these requirements in place, design the following:
1. The tree data structure
2. An efficient numbering algorithm for the tree nodes
The tree should support the following operations:
Insertion of individual nodes at any level
Bulk insertion of nodes at any level (As far as possible, bulk insertion should not result in any renumbering of any parent/sibling node number ranges)
I have a tree-like structure, which is constructed by
struct TreeNode
{
std::vector<TreeNode*> p_PrevLevelNodes;
std::vector<TreeNode*> p_NextLevelNodes;
}
and there is some root node stored. In contrast to a classical tree, a Node might have multiple root nodes. All of these root nodes are present in the "classical" tree, but there are so to say additional link ups.
To come to my question: I have to communicate this structure between different instances by both MPI and tcp. Hence, I need some kind of serialization, but dont really know where to start.
Any hints?
What is your tree? Your tree is a pointer pRoot to one of such nodes (TreeNode). Since you have pRoot, you can build list of upper nodes (it is empty for pRoot in usual situation) and list of lower nodes. So you can build list of visited nodes + save additional information about them. And for each of these nodes in list you can repeat all these operations. So you will have big list of nodes with additional information - it is easy to serialize this list instead of you tree.
(Actually it is not necessary to build intermidiate data structure to serialize, but I propose to remember about this structure to simplify implementation of you algorithm)
Something similar was implemented here: http://basicalgos.blogspot.ru/2012/04/44-serialize-and-de-serialize-tree.html (there is much simplier tree, but I think you can repeat this logic for your tree).
Also it might be useful for you to read http://eli.thegreenplace.net/2011/09/29/an-interesting-tree-serialization-algorithm-from-dwarf/
I'm doing an implementation of the BFS algorithm in c++ to find a spanning tree, the output for a spanning tree should be shown in preorder, but I have a doubt in the implementation, how I can build a tree if not exactly know how many children have each node?. Considering a tree structure recursive The data structure of the tree can be written as:
typedef struct node
{
int val;
struct node *left, *right;
}*tree; //tree has been typedefed as a node pointer.
But do not think it works this implementation as mentioned before.
This is my function to return the tree in preorder:
void preorder(tree t)
{
if(t == NULL)
return;
printf("%d ", t->val);
preorder(t->left);
preorder(t->right);
}
I also wonder if there is any way to do the preorder of the nodes without using a tree structure.
I have seen two concrete questions in the posting:
Is it possible to have a data structure using more than two children in a tree? Of course this is possible. Interestingly, it is even possible with the node structure you posted! Just consider the left pointer to be a pointer to the first child and the right pointer to point to the next sibling. Since breadth first search of a graph implicitly builds up a spanning tree, you can then walk this tree in preorder if you actually represent it somehow.
Can you do a preorder walk without using a tree structure? Yes, this is possible, too. Essentially, DFS and BFS are conceptually no different for this: you just have a data structure maintaining the nodes to be visited next. For DFS this is a stack, for BFS this is a queue. You get a preorder walk of the tree (i.e. you visit all children of a node after the parent) if you emit the node number when you insert it into the data structure maintaining the nodes to be visited.
To expand a bit on the second point: a preorder walk of a tree just means that each node is processed prior to it child nodes. When you do a graph search you want to traverse through a connected component of a graph, visiting each node just once, you effectively create an implicit tree. That is, your start node become the root node of the tree. Whenever you visit a node you search for adjacent nodes which haven't been visited, i.e. which isn't marked. If there is such a node, the incident edge becomes a tree node and you mark the node. Since there is always only just one node being actively held you need to remember the nodes which aren't processed, yet, in some data structure, e.g. a stack or a queue (instead of using a stack explicitly you could do recursion which creates the stack implicitly). Now, if you emit the node number the first time you see a node you clearly process it prior to its children, i.e. you end up writing the node number the order of a preorder walk.
If you don't understand this, please whip out a sheet of paper and draw a graph and a queue:
the nodes with hollow circles and their node number next to them
the edges with thin lines
the queue is just rectangles which doesn't contain anything at the start
Now choose a node to become the start node of your search which is the same as the root node of your tree. Write its number into the first empty position in the queue and mark i.e. fill the node. Now proceed with the search:
look at the node indicated by front of the queue and find an adjacent node which isn't filled:
append the node at the back of the queue (i.e. right behind the last node in the rectangle)
mark (i.e. fill) the node
make the line connecting the two nodes thicker: it is a tree edge now
if there are no further unmarked adjacent nodes tick the front node in the queue off (i.e. remove it from the queue) and move on to the next node until there are no further nodes
Now the queue rectangle contains a preorder walk of the spanning tree implied by a breadth first search of the graph. The spanning tree is visible using the thicker lines. The algorithm would also work if you treated the rectangle for the queue as a stack but it would be a bit messier because you end up with ticked off nodes between nodes still to be processed: instead of looking at the first unticked node you would look at the last unticked node.
When working with graph algorithms I found it quite helpful to visualize the algorithm. Although it would be nice to have the computer maintain the drawing, the low-tech alternative of drawing things on paper and possibly indicating active nodes by a number of labeled pencils works as well if not better.
Just a comment on the code: whenever you are reading any input, make sure that you successfully read the data. BTW, your code is clearly only C and not C++ code: variable length arrays are not available in C++. In C++ you would use std::vector<int> followOrder(vertexNumber) instead of int followOrder[vertexNumber]. Interestingly, the code isn't C either because it uses e.g. std::queue<int>.