Looking for some help while practicing Binary Search Trees. I am unable to figure out where I am going wrong in my code, as it seems to follow the generic recursion format. Possibly something related to either the temp Node or the return statement? Any help would be appreciated thanks.
public static Node < Integer > mirror(Node < Integer > root) {
if (root == null)
return null;
else {
mirror(root.left);
mirror(root.right);
Node temp = root.left;
root.left = root.right;
root.right = temp;
return root;
}
}
First, it seems you do not allocate memory for the nodes that will belong to the mirrored tree. Note that the instruction
Node temp;
does not allocate in the heap, but in the stack. When the function returns, this memory is freed and whatever you have stored there won't make sense.
Second, it seems you do not have very clear the traversal pattern and I think that because of the line
root.right = temp;
poses an kind of asymmetry.
This is a way (in C++ pseudo-code), among others, for getting a mirrored binary tree that uses a preorder pattern:
Node * mirror(Node * root)
{
if root == NULL
return NULL;
Node * mirror_root = new Node;
mirror_root->left = mirror(root->right); // here is where the mirroring happens
mirror_root->right = mirror(root->left);
return mirror_root;
}
You could try to do the same thing allocating the nodes in postorder or inorder.
Related
I'm attempting to traverse through a B+ Tree and add the elements from the leaves into an ArrayList with the following code:
public void toArrayList(Node node){
Node currentNode = node;
if(currentNode instanceof InnerNode){
InnerNode inner = (InnerNode) currentNode;
int i = 0;
int temp = inner.children.length;
while(i < temp){
currentNode = inner.children[i];
toArrayList(currentNode);
i++;
}
}
if(currentNode instanceof LeafNode){
LeafNode leaf = (LeafNode) currentNode;
int j = 0;
int temp = leaf.values.length;
while(j < temp){
if(leaf.values[j] != null) {
retArray.add(leaf.values[j]);
}
j++;
}
}
}
What it does is it checks if the node is an instance of an Inner Node or a Leaf Node. If it is an Inner Node it recursively calls the function with each of its children. If it is a Leaf Node then it will add the values into the ArrayList. However while running this fucntion I end up getting a java.lang.OutOfMemoryError.
Is there a way to make my code more efficient or should I look to take a different approach to this method?
Unless your tree structure has a few million elements in it, what's going on here is that some InnerCode contains itself, and thus this code keeps going forever, or, at least, until your retArray fills up.
Also note that this code will add a leaf node twice if it's the last child of an inner node. I strongly suggest you don't overwrite locals like this. Also, for loops are just more compact here (note that making this code smaller is not going to make any difference at all for memory issues; OOMError refers to the heap, and locals don't live there).
This question also applies to various linked lists methods as well. So, when I have a method:
public void insert(String key)
{
if(top == null)
{
top = new Node(key);
}else {
Node newNode = new Node(key);
Node rover = top;
Node prev = top;
boolean wentLeft = true;
while(rover != null)
{
if (rover.getName().compareTo(key) < 0)
{
prev = rover;
rover = rover.getRight();
wentLeft = false;
}else {
wentLeft = true;
prev = rover;
rover = rover.getLeft();
}
}
if(wentLeft == true)
{
prev.setLeft(newNode);
}else {
prev.setRight(newNode);
}
}
nElems++;
}
How is the top of the Binary Search Tree and its children updated despite not being directly set anywhere in the method?
I know this likely has something to do with shallow copying and that like rover/prev are still referencing top in memory but I still don't really get it.
Even though I feel like I understand Linked Lists and Binary Search Trees on a conceptual level I don't feel comfortable moving forward with them without understanding this.
There are no copies being made. When you assign prev = top, that only creates another reference to the same object as top, not a copy.
The code works because nodes are inserted one by one.
When prev.setLeft/setRight is called, prev is already in the tree because it was inserted before. So prev is already in the tree, i. e. the parent of prev is top, or the parent of the parent of prev, you get the idea. Thus, when new_node becomes child of prev, it becomes part of the tree.
This is what makes linked lists and trees so useful. When you insert an element, you only have to make one connection.
You are given a pointer to the root of a binary search tree and a value to be inserted into the tree. Insert this value into its appropriate position in the binary search tree and return the root of the updated binary tree. You just have to complete the function.
I have given my code but one test case is not working. Here is my code:
static Node Insert(Node root,int value){
Node d =root;
Node q = new Node();
q.left = null;
q.right=null;
q.data = value;
while(true){
if(value<d.data){
if(d.left==null){d.left = q;
return root; }
else{
d= d.left ;
}
}
else{
if(value>d.data){
if(d.right==null){d.right=q;
return root;}
else d = d.right;
}
}
}
}
You're missing two cases: value == d.data and the empty tree.
value == d.data: In that case the tree won't be altered in any way, but your code won't break-off and end up in an infinite loop.
Simplest solution would be to insert these lines in the while-loop:
if(value == d.data)
return root;
The case where the tree is empty is rather implementation-specific, so it's difficult to suggest any solution for this case.
I have a tree structure that looks like the following:
Tree {
Node root;
}
Node {
List children;
}
And I'm trying to make a method that returns the length of the longest path. I've seen some solutions that work when it's a binary tree, but there is no limit to how many children nodes each node can have and that is where I'm running into problems.
I should do somethinkg like this
int getLongestPathLength(Node node) {
if(node == null) return 0;
int max = 0;
for(Node child : node.children){
max = Math.max(getLongestPathLength(child),max);
}
return 1+max;
}
It seems what you are looking for it called the height of the root. You can see the basic algorithm to compute it here (similar to the one given in the previous answer): http://cs.nyu.edu/courses/fall02/V22.0310-002/lectures/lecture-08.html.
I am trying to make a (spanning) tree that comes naturally from traversing a graph (undirected and connected) using Breadth First Search, but I am having difficulties modifying the algorithm such that it makes a tree. I am using Java.
Here is my BFS algorithm.
public void traverse(Node node){
Queue queue= new Queue();
node.visited= true;
//Maybe do something here?
queue.enqueue(node);
while (!queue.isEmpty()){
Node r= queue.dequeue();
for (int i= 0; i < r.childen.size(); i++){
Node s= (Node)r.childen.get(i);
if (s.visited == false){
//And do something here?
s.visited= true;
queue.enqueue(s);
}
}
}
}
My graph data structure is simply this (note it's undirected and connected) :
public class Graph {
Node mainNode; ...
And the tree data structure is also simply this:
public class Tree {
Node root; ...
My Node is like this:
public class Node<T> {
T data;
boolean visited= false;
ArrayList<Node> childen= new ArrayList<Node>();
...
I think my trouble comes from the fact that I can't simply add some Node node from the graph directly to my tree (because this node would have all its children already). Instead, I have to make a new Node(node.data) so that the added node in the tree doesn't point to all the adjacent nodes that the same node would point in the graph.
So my question: how do I make a (spanning) tree out of graph while traversing the said graph using Breadth First Search?
I'm going to operate off the assumption that the graph is both undirected and connected. That being said, I think you're on the right track, but you're going to need a few more things. First, I highly encourage you to keep your search state and node implementation separate - in other words, it's not a great idea to store a private member variable Node.visible just to aid your search.
You can avoid this by maintaining some extra state inside your search method, and use a recursive private helper method to hide that state from callers of your public traverse() method. You will need to properly implement equals and hashCode in your Node class to do this.
Also - if you are wanting to create a completely separate Tree with different nodes, you'll want to essentially create new, empty instances of each Node in the Graph and first populate them with their counterpart's data, then build the tree using the cloned nodes. That said, here's some code to get you going (I haven't tested this, but it should give you an idea of what to do):
/**
* This facade method traverses just the root of the new tree. All recursion is
* passed to the "traverseHelper(3)" recursive method.
*/
public Tree<T> traverse(Graph<T> g){
if(g == null || g.mainNode == null) return null;
Node<T> node = g.mainNode;
Node<T> clone = new Node<T>(node.data); //this is the root of our new Tree
Set<Node<T>> searched = new HashSet<Node<T>>(); //accumulates searched nodes
searched.add(node);
traverseHelper(node,clone,searched);
return new Tree<T>(clone);
}
/**
* Recursively performs BFS on all the children of the specified node and its
* corresponding cloned instance.
*
* Assumes that "node" has been added to "searched" and that
* "searched.contains(node)" AND "searched.contains(clone)" will return true by
* the time this method is called.
*/
private void traverseHelper(Node<T> node, Node<T> clone, Set<Node<T>> searched){
if(node.children == null) return;
Map<Node<T>,Node<T>> toRecurseOn = new HashMap<Node<T>,Node<T>>();
//This is the Breadth-First part - builds the next leaves in the tree:
for(Node<T> child : node.children){
if(child == null || searched.contains(child)) continue;
Node<T> childClone = new Node<T>(child.data); //create leaf in the tree
clone.children.add(childClone); //builds the current level in the tree
childClone.children.add(clone); //maintains undirected-ness of the tree
toRecurseOn.put(child,childClone); //lets us BFS later
}
//This is the Search part - builds the subtrees:
Iterator<Node<T>> i = toRecurseOn.keySet().iterator();
while(i.hasNext()){
Node<T> child = i.next();
Node<T> childClone = toRecurseOn.get(child);
i.remove(); //Saves a little memory throughout the recursion
traverseHelper(child,childClone,searched);
}
}
I found a simple answer to my question. Instead of building a tree, I remove edges which lead to already visited nodes (this information we get for free as part of the BFS algorithm). Below is my implementation (it might be modified if one doesn't want to destroy the initial graph structure).
public static Tree BFS(Node node){
Queue queue= new Queue();
node.visited= true;
queue.enqueue(node);
while (!queue.isEmpty()){
Node r= queue.dequeue();
for (int i= 0; i < r.childen.size(); i++){
Node s= (Node)r.childen.get(i);
if (s.visited == false){
s.visited= true;
queue.enqueue(s);
}
else{
//Remove edge here
r.childen.remove(i);
i--;
}
}
}
Tree tree= new Tree(node);
return tree;
}
EDIT. The following is an implementation which doesn't destroy the initial graph structure by keeping a separate queue.
public static Tree BFS(Graph G, Node node){
Queue queue= new Queue();
Queue treeQueue= new Queue();
ArrayList<Node> tempV= new ArrayList<Node>();
tempV.add(node);
queue.enqueue(node);
Node root= new Node(node.data);
treeQueue.enqueue(root);
while (!queue.isEmpty()){
Node r= queue.dequeue();
Node t= treeQueue.dequeue();
for (int i= 0; i < r.childen.size(); i++){
Node s= (Node)r.childen.get(i);
if (tempV.indexOf(s) < 0){
tempV.add(s);
Node child= new Node(s.data);
t.childen.add(child);
queue.enqueue(s);
treeQueue.enqueue(child);
}
}
}
Tree tree= new Tree(root);
return tree;
}