BFS on a tree with lists - java

So I'm building this tree which has 1..* Nodes where each node has a list which in themselves can have 1..* nodes.
The first three levels of the tree I can build just fine but then it won't work more if I don't code all the levels which are just plain stupid. The solution is of course to use some kind of recursive method and a BFS.
Basically, in my TreeBuilder class, I want to be able to call tree.getNodesAtDepth(depth)) and get a list of all nodes that are at that depth. Problem is that I don't understand how I can implement the getNodesAtDepth(depth) method.
All the examples I find are for binary trees. An alternative is to have the addChild method take a depth argument so I can specify at which depth to insert the child at.
In the end, this is what I want:
I have a tree with a root. The root has a list which has 4 children nodes. I want to get the 4 children. For each child generate three nodes. So for child 0 has 3 children, child 1 has 3 children, child 3 has 3 children and child 4 has 3 children. And so forth
Maybe a possible soultion is to have a level attribute on each node and search for that node and then return it's parent. Beacuse it's parent should have a list of all the nodes at the searched for node.

Try this method :
static void getNodesAtDepth(Node root, int currentLevel, int level, List<Node> nodes) {
if(root == null) return;
if(level == 0) {
nodes.add(root);
return;
}
if(currentLevel + 1 == level) {
if(root.getNodeList() != null) {
nodes.addAll(root.getNodeList());
}
}
if(currentLevel < level) {
if(root.getNodeList() != null) {
for(Node node : root.getNodeList()) {
getNodesAtDepth(node, currentLevel + 1, level , nodes);
}
}
}
}
How to use it :
List<Node> nodeList = new LinkedList<>();
getNodesAtDepth(root, 0, 2, nodeList);
root of course is the root of your tree. nodeList will store all your nodes at desired level (in my case it's 2). Second parameter is always 0, (that's for keeping track of the current level)

If I assume your class tree structure is :
class Tree {
List<Tree> children
...
}
Then you can recursively iterate through the tree until you find the expected depth:
void recursivelyCollectNodesAtDepth(int depth,
List<Tree> nodesAtDepth,
Tree tree,
int currentDepth) {
if (tree == null) {
return;
}
if (depth == 0) {
nodesAtDepth.add(tree);
} else if (currentDepth + 1 == depth) {
// add children to the node list when expected depth is reached
if (tree.getChildren() != null) {
nodesAtDepth.addAll(tree.getChildren());
}
} else if (currentDepth < depth) {
// iterate and recursively travers through child nodes
for (Tree childTree : tree.getChildren()) {
recursivelyCollectNodesAtDepth(depth,
nodesAtDepth,
childTree,
currentDepth + 1);
}
}
}
Here the tree nodes a recursively traversed to the expected level

Related

How to make an efficient algorithm for chopping a binary search tree into two by given value?

I implemented public BinarySearchTree<Node,T> chop(T x)
that chops my tree into two parts at element x. The SSet this will contain elements < x, and the returned SSet is a SSet that contains elements >= x. This should work for all elements regardless of whether they are in this.
For example, suppose s={2,4,6,8}. Then s.chop(3) returns {4,6,8} and s becomes {2}. We would get the same result for s.chop(4).
The slowChop method is implemented, but it has a time complexity of O(n), but I need to reduce it to at least O(h) when the tree is balanced (where h is the height of the tree).
public BinarySearchTree<Node,T> slowChop(T x) {
Node sample = super.newNode();
BinarySearchTree<Node,T> other = new
BinarySearchTree<Node, T>(sample);
// Iterate through the n nodes in-order.
// When see value >=x, add to new BST in O(height) time, and
// remove it from this BST (on next iteration) in O(height) time.
Iterator<T> it = iterator();
T prev = null;
while( it.hasNext() ) {
T curr = (T)(it.next());
if( c.compare(curr, x) >= 0 ) { // we have our first >= x
other.add(curr);
if( prev != null ) {
this.remove(prev); // safe to remove now
}
prev = curr;
}
}
if( prev != null ) {
this.remove(prev); // edge case, get that last one!
}
return other;
}
public BinarySearchTree<Node,T> chop(T x) {
Node sample = super.newNode();
BinarySearchTree<Node,T> other = new
BinarySearchTree<Node, T>(sample);
// TODO: Implement this method. It should match slowChop in
// behaviour, but should be faster :-)
return other;
}
Indeed, your algorithm is not making use of the efficiency that you can get from the fact you are dealing with a binary search tree. So iterating through the tree with an in-order traversal is not the way to go.
Instead, perform a binary search and cut the edges that link two nodes which should end up in different trees. While cutting you'll also need to reattach nodes to where a previous cut was performed. The complexity is the same as a binary search towards the bottom of the tree, and so it is O(logn).
Here is an implementation that assumes you have the regular getters and setters:
on the Node class: getLeft, setLeft, getRight, setRight, getValue, and
on the BinarySearchTree class: getRoot, setRoot
public BinarySearchTree<Node,T> chop(T x) {
// Create two temporary dummy (sentinel) nodes to ease the process.
Node rightRootParent = super.newNode();
Node leftRootParent = super.newNode();
// Set "cursors" at both sides
Node rightParent = rightRootParent;
Node leftParent = leftRootParent;
// Start the binary search for x, cutting edges as we walk down
Node node = this.getRoot();
while (node != null) {
// Decide for each node in the binary search path at which side it should go
if (c.compare(node.getValue(), x) >= 0) {
// Node should belong to the right-side tree
rightParent.setLeft(node); // Establish edge
rightParent = node;
node = node.getLeft(); // Move down
rightParent.setLeft(null); // Cut next edge for now (it might get restored)
} else { // Symmetric case
leftParent.setRight(node);
leftParent = node;
node = node.getRight();
leftParent.setRight(null);
}
}
// Set the roots of both trees
this.setRoot(leftRootParent.getRight());
return BinarySearchTree<Node, T>(rightRootParent.getLeft());
}

Finding a way between two nodes in a grah (Storing the nodes passed)

I have got a graph, and I would like to find a path between two nodes (number 3 and 5).
I read about finding paths in graph, and I tried to write DFS and BFS. Both are implemented and works well. However, I would like to get a list of each node visited directly from 3 to 5.
Both algorithms work as they supposed to so, when running bsf I will visit nodes in such order: 2,6,1,4,5.
Using dfs 2,1,4,5.
But what I would like to do achieve is 6,5 (in first case) and 2,4,5 in second.
In other words, I want to save only nodes that are on the way from 3 to 5 (Not all visited during dfs/bfs), as a List of nodes.
I have been racking my brain for a long time, how to change my code to achieve it, or maybe should i change my approach? I should should store nodes in the correct path, or use different algorithm? I simply do not have idea how to do it.
My bfs
public List<Node> bfs(Node root, Node nodeWeSearchFor)
{ Queue<Node> queue = new LinkedList<Node>();
List<Node> route = new ArrayList<Node>();
if(root == null || nodeWeSearchFor == null) return route;
//State is just an enum Visited or unvisited
root.state = State.Visited;
//Adds to end of queue
queue.add(root);
while(!queue.isEmpty())
{
//removes from front of queue
Node r = queue.remove();
//Visit child first before grandchild
for(Node n: r.getConnectedNodes())
{
if(n.state == State.Unvisited)
{
queue.add(n);
route.add(n);
n.state = State.Visited;
//If we found node, return
if(n==nodeWeSearchFor){
return route;
}
}
}
}
return route;}
My dfs:
public List<Node> dfs(Node root, Node nodeWeSearchFor)
{
List<Node> route = new ArrayList<Node>();
//Avoid infinite loops
if(root == null) return route;
System.out.print(root.toString() + "\t");
root.state = State.Visited;
route.add(root);
if(root == nodeWeSearchFor) return route;
//for every child
for(Node n: root.getConnectedNodes())
{
//if childs state is not visited then recurse
if(n.state == State.Unvisited)
{
//recursive call for dfs (We are passing route)
dfs(n,nodeWeSearchFor,route);
}
}
return route;
}
public List<Node> dfs(Node root, Node nodeWeSearchFor,List<Node> _route)
{
List<Node> route = _route;
//Avoid infinite loops
if(root == null) return route;
System.out.print(root.toString() + "\t");
root.state = State.Visited;
route.add(root);
if(root == nodeWeSearchFor) return route;
//for every child
for(Node n: root.getConnectedNodes())
{
//if childs state is not visited then recurse
if(n.state == State.Unvisited)
{
dfs(n,nodeWeSearchFor,route);
}
}
return route;
}
It is quite easy, in DFS, when you reach the "end" (you cannot go forward), you have to "go back". So when you are going "back", you just remove that node at the "dead end" from your list of visited nodes.
In BFS, you have to create new list for each node visited, copy the already visited nodes of node that "opens him" and then add itself to that list.

Depth first search list paths to all end nodes

Hi I have a tree in which I would like to get paths from the initial (root) node to all leaves.
I found several algortithms that list (all) apths betwenn any given two nodes within a graph (for example this SO question:
Graph Algorithm To Find All Connections Between Two Arbitrary Vertices)
For binary tree there also exists an algorithm
http://techieme.in/print-all-paths-in-a-tree/
but I work on a tree with various branching factors.
Is there any better way of achieving what I want to do than traversing the tree once in order to get all leaves and then run the algorithm above for all leaves combined with the initial node?
I was thinking about implementing simple DFS extended by some additional stack containing all nodes alongt he path to a single leaf and then listing all sentences by looping through these stacks.
ArrayList<GrammarNode> discovered = new ArrayList<GrammarNode>();
Stack<GrammarNode> S = new Stack<GrammarNode>();
while (!S.empty()) {
node = S.pop();
if (!discovered.contains(node)) {
discovered.add(node);
System.out.println(node.getWord.getSpelling().trim());
for (GrammarArc arc : node.getSuccessors()) {
S.push(arc.getGrammarNode());
}
}
}
UPDATE:
The problem of this is that one has alyways go back to the root in order to generate full sentences. So I guess the question is: How to remember the node which was already fully visited (this means where all children nodes were already explored)?
Printing all paths from the root to every leaf would mean to print the entire tree so I'd just use a simple DFS and do the following for each node:
add it to the list/stack
if the node has children, repeat for the children
if the node is a leaf, print the list/stack
pop the node from the list/stack
Example:
A
/ \
B E
/ \ / \
C D F G
The first steps would look like this:
put A on the list -> {A}
put B on the list -> {A,B}
put C on the list -> {A,B,C}
since C is a leaf, print the list (A,B,C)
remove C from the list -> {A,B}
put D on the list -> {A,B,D}
since D is a leaf, print the list (A,B,D)
...
if you know that the graph is indeed a tree (there is only one path to each node), them yes, a simple DFS would be more efficient (at least from a memory usage point of view). Otherwise, you can also use the iterative deepening DFS.
So here's a sample approach. Note that you need an extra visited field in your node structure:
public class TreeNodeExtra {
int val;
TreeNodeExtra left;
TreeNodeExtra right;
boolean visited;
TreeNodeExtra (int v) {
val = v;
visited = false;
}
}
private ArrayList<ArrayList<TreeNodeExtra>> all_path_from_root_to_leaf(TreeNodeExtra root) {
Stack<TreeNodeExtra> st = new Stack<>();
ArrayList<ArrayList<TreeNodeExtra>> res = new ArrayList<>();
st.push(root);
root.visited = true;
while (!st.isEmpty()) {
TreeNodeExtra top = st.peek();
if (top.left != null && !top.left.visited) {
st.push(top.left);
top.left.visited = true;
}
// if left node is null
else {
if (top.right == null && top.left == null) {
// we have a leaf
ArrayList<TreeNodeExtra> tmpList = new ArrayList<>();
for (TreeNodeExtra t : st) {
tmpList.add(t);
}
res.add(tmpList);
st.pop();
}
else if (top.right != null && !top.right.visited) {
st.push(top.right);
top.right.visited = true;
}
else {
st.pop();
}
}
}
return res;
}
A slight modification of DFS (which includes back-tracking) prints all the paths from a given source. In the below example the graph is represented in adjacency list format.
public void mDFS(ArrayList<node> v,int ind,ArrayList<Boolean> visit,ArrayList<node> tillNow){
visit.set(ind,true);
node n = v.get(ind);
int len = n.adj.size();
tillNow.add(n);
int count = 0;
for(node tmp: n.adj){
if( !visit.get(tmp.id) ){
count++;
tmp.pre = ind;
mDFS(v,tmp.id,visit,tillNow); // id gives index of node in v
}
}
if(count == 0){
for(node tmp: tillNow){
System.out.print((tmp.id + 1) + " - ");
}System.out.print("\n");
}
visit.set(ind,false);
tillNow.remove(tillNow.size() - 1);
return;
}

find successor in AVL tree

there is avl tree with nodes, and each node has only 3 fields:
1.right child
2.left child
3.value(key)
notice that it doesnt have such field "parrent" or "father".
my question is: in case we want to know the successor of EVERY node in the tree,
and without use any LinkedList or any collection, what is the method to do so?
You could do something like this
// Returns the last node in the inorder traversal of tree,
// or prev if tree is null.
Node printSuccessors(Node tree, Node prev) {
if (tree == null) {
return prev;
}
Node lastLeft = printSuccessors(tree.leftChild(), prev);
if (lastLeft != null) {
System.out.println("The successor of " + lastLeft.key()
+ " is " + tree.key());
}
return printSuccessors(tree.rightChild(), tree);
}
and then call printSuccessors(root, null).

Binary search tree level order with parent node

Hi I am trying to print out level order of a binary search tree in the format (node element, parent node element). I am currently using queues to get the level order but I am having a hard time getting the parent node. Is it possible to do with queues? If so how would I go about doing it? If not what is a more optimal way of doing it? Thank you!
For example with the following tree:
6
/ \
5 7
Level 0: (6, null)
Level 1: (5, 6) (7, 6)
So unfortunately there isn't a way of doing this strictly with one queue, assuming your nodes only have a left,right, and value. The problem is once you get to depths > 0, the nodes at that level might have different parents, and that information is gone unless you store it in some fashion.
The easy way to do this is to just add a Node parent inside of your Node class. Barring that, you could also make a inner class that holds the mapping of the Node to parent node, or you could use any number of data structures. Below I included how to do this with hashmaps.
public void printLevelOrder(){
Queue<Node> q = new LinkedList<Node>();
Map<Node, Node> parents = new HashMap<Node,Node>();
Node nextLevel = null;
q.add(this);
int lvl = 0;
while (!q.isEmpty()){
Node n = q.remove();
if (n == nextLevel || nextLevel == null){
System.out.print("\nlvl " + lvl++ +" ");
nextLevel = null;
}
System.out.print("("+n.value +","+parents.remove(n)+")");
if (n.left != null){
q.add(n.left);
parents.put(n.left, n);
if (nextLevel == null)
nextLevel = n.left;
}
if (n.right != null){
q.add(n.right);
parents.put(n.right, n);
if (nextLevel == null)
nextLevel = n.right;
}
}
}
To print the nodes by level I do the following. The next level is determined by adding the first non null nextLevel node. When we have reached that node, we know we are at the start of the next line, and null it out again.

Categories