Binary Tree constructor from linear array - java

NOTE: This IS homework, so please do not give me the answer right out, but pointers would be helpful.
Assignment overview:
(Test each method to ensure that it works properly.)
Generate a binary search with 100 elements added in the correct order - add the numbers 1 through 100 to the tree in the correct order add 1, then 2, then 3, etc.
Generate a binary search with 100 elements add in revers order - add the numbers 100, 99, 98 and so on.
Generate a binary search with 100 randomly generated elements.
The reason I said a linear array in the question is because the root has to be the first element in the array and then add the rest.
I do not have all the other methods required to properly test if the tree was made properly, and I am about to leave for work. However, I am posting below the start of the algorithm that I think will work, just not sure.
public BST(int[] numbers)
{
node root;
node currentParent;
node previousParent = null;
int i = 1; // skip the root, that will be handled manualy
root = new node(numbers[0]); // first element is the root
currentParent = root;
// handle right hand side of binary tree first
while (i > root.getValue())
{
while (i > currentParent.getValue())
{
node newNode = new node (numbers[i]);
currentParent.setRightChild(newNode);
previousParent = currentParent;
currentParent = newNode;
i++;
} // end inner while
if (previousParent.leftChild == null)
{
node newNode = new node(numbers[i]);
previousParent.leftChild = newNode;
currentParent = newNode;
i++;
} // end if branch
else
{
System.out.println("Hmm, something seems to be wrong!");
} // end else
} // end right side binary tree while
} // end integer array constructor
This is pretty much the whole algorithm, I would have to do it again but reverse the < and > signs (if this is correct). Am I on the right path with this algorithm?
Adding the node class as requested.
public class node
{
node leftChild; // left pointer
node rightChild; // right pointer
int value; // will be the int value inside the node
boolean isLeaf; // boolean for determing if a node is a left node or not
/*
Null constructor for the class. Sets the pointers to null
*/
public node ()
{
leftChild = null;
rightChild = null;
} // end null constructor
/*
Intialzing constructor that will take a single integer as input
*/
public node (int number)
{
leftChild = null;
rightChild = null;
value = number;
} // end intialzing constructor with int input
/*
The setValue method will take the int value inputted from the array into
a new node
*/
public void setValue(int number)
{
value = number;
} // end setValue()
/*
The getValue method will return to the user the value that is stored
inside a specific node.
*/
public int getValue()
{
return value;
} // end getValue()
/*
The setLeftChild method will set the pointers to the nodes left child
which will be a value that is equal or lower to the paret node
*/
public void setLeftChild (node leftChild)
{
this.leftChild = leftChild;
} // end setLeftChild()
/*
The setRightChild method will be the same as setLeftChild above but will
handle setting the nodes right child. The right child will be a value
that is greater than the parent node
*/
public void setRightChild(node rightChild)
{
this.rightChild = rightChild;
} // end setRightChild
/*
the getLeftChild method will return to the user/calling method what the
left child of a given node is.
*/
public node getLeftChild (node currentNode)
{
return leftChild;
} // end getLeftChild()
/*
the getRightChild method is exactly the same as the getLeftChil method
above, except it will return the right child instead
*/
public node getRightChild(node currentNode)
{
return rightChild;
} // end getRightChild()
/*
The setLeaf method will be in charge of manipulating a boolean value and
setting it to true if the node is a left or not
*/
public void setLeaf(boolean leaf)
{
if (leaf == true)
{
isLeaf = true;
} // end if
else
{
isLeaf = false;
} // end else
} // end setLeaf
/*
The getLeaft method will simply return a boolean value that indicates if
the given node is a left node or not
*/
public boolean getLeaf()
{
return isLeaf;
} // end getLeaf()
} // end node class

No, sorry, this is wrong.
You are comparing indices with data values. You should only compare the same things to the same things. Imagine the task is to put the numbers 1001 through 1100 into the tree, rather than 1 through 100. It will make it easier to distinguish between indices and data values (and the distinction is very subtle here because your indices are 0 through 99 and your data values 1 through 100).
You cannot assume that you "handle the right hand part first". You have to decide whether the given item will go left or right based on its value, and whether it's less than or greater than the current node's value.
Trying to add all high values first and then all low values will not work, if you have an unordered array.
One last tip: the class should be named Node, not node. Classes and all type names should start with a capital, variables, fields and method names should start with a lowercase letter, and constants should be in all-caps.

Related

How to get the left and right child of a node in an unordered binary search tree?

I'm stuck with this problem: The method below must return the value in the left child node, or -1 if it not exist.
public int getLeftChild(int el) {...}
/* Same for the right child */
Now, the argument is an int value, that indicates the value of the parent node.
Another issue is that... the tree is not ordered, and there are only positive integer values.
So, I can have a value of 0 in the root, 3 in the left child and 1 in the right child, and so on...
I can't figure out how to resolve this.
I can't use ADTs like LinkedList or Stack for any purpose.
The binary tree class has a field root, of type Node:
public class Node {
private int value;
private Node leftChild;
private Node rightChild;
/*Getters and Setters...*/
}
Something like this would work:
public int getLeftChild(int el) {
int not_found = -1;
Stack<Node> nodes_to_search = new Stack<>();
nodes_to_search.add(this);
while(!stack.isEmpty()){
Node root = nodes_to_search.pop();
if(root.value == el){
return (root.leftChild != null) ? root.leftChild.value : not_found;
}
if(root.leftChild != null) nodes_to_search.push(root.leftChild);
if(root.rightChild != null) nodes_to_search.push(root.rightChild);
}
return not_found;
}
You have to search in both the left and right subtrees since the tree is not sorted. Every time you find a valid subtree (i.e., not null) you added to the stack of elements to search. You stop the search when your searching criteria is meet.

Remove recursively from a binary search tree

This is homework; please don't just give me code
I have two methods: remove(T data) and removeRec(Node<T> node, T data).
In its current state, it seems my code only removes the root node of the BST.
#Override
public T remove(T data) {
if (data == null) {
throw new IllegalArgumentException("Data is null");
}
if (root == null) {
throw new java.util.NoSuchElementException("BST is empty");
} else {
size--;
BSTNode<T> dummy = new BSTNode<T>(null);
return removeRec(root, data, dummy).getData(); //This is probably wrong too
}
}
/**
* Helper method to recursively search for, and remove the BSTNode with
* the given data in it
* #param node is the node we're currently at
* #param data is the data we're looking for
* #param temp I have no idea why
* #return node that was removed
*/
private BSTNode<T> removeRec(BSTNode<T> node, T data, BSTNode<T> temp) {
if (compare(data, node.getData()) < 0) {
temp.setLeft(removeRec(node.getLeft(), data, temp));
} else if (compare(data, node.getData()) > 0) {
temp.setRight(removeRec(node.getRight(), data, temp));
} else if (node.getLeft() != null && node.getRight() != null) {
temp.setData(findMin(node.getRight()).getData());
temp.setRight(removeRec(node.getRight(), data, temp));
} else {
if (node.getLeft() != null) {
temp = node.getLeft();
} else {
temp = node.getRight();
}
}
return temp;
}
private int compare(T a, T b) {
return a.compareTo(b);
}
My instructor has told me (as a hint) that I should see what passing in a third argument into the method, in this case, BSTNode<T> temp. I don't understand how that helps though, or how to utilize it. I don't see how using a third argument helps; and I can't find anything online as to why you'd do this either.
There are three main possibilities when you try to remove data from your Binary Search Tree:
data is less than the current node value: Call remove on the left subtree or throw a NoSuchElementException if it is null.
data is greater than the current node value: Call remove on the right subtree or throw a NoSuchElementException if it is null.
data is equal to the current node value.
1 and 2 are pretty straightforward, but 3 has four more cases to consider:
3.1. current node is a leaf: Both left and right subtrees are null. Just replace the reference to the current node in its parent by null.
3.2. current node has only the left child: You need to make the parent of the current node point to the left subtree, thus removing the current point. To do this, you can implement a function that will check if the current point was on the left or right subtree of the parent and replace it accordingly. Calling it would look like this:
replaceNodeInParent(node, node.getLeft(), parent);
3.3. current node has only the right child: Similar to 3.4, but using getRight() instead of getLeft().
3.4. current node has both the left and right children: You should maintain the property of the BST that all nodes on the left are less than the current node and all nodes on the right are greater than the current node. To do so, you should find the smallest value on the right, copy it to the current node, and delete it from the right subtree. Something like this:
BSTNode<T> successor = findMin(node.getRight());
node.setData(successor.getData());
removeRec(node.getRight(), successor.getData(), node);
It looks like your BSTNode doesn't hold a reference to the parent node. If so, I believe that's what the third argument for removeRec should be. You will need a reference to the parent every time you replace the current node, so you can set the parent left or right subtree as needed.
For further reading, you can check this article on Binary Search Trees from Wikipedia.

Deleteing a Node in a Binary tree

Iunderstand the basis of a deletion algorithm in a Binary Search tree and have created the following code to delete the largest value from the tree.
public void DelLargest()
{
Node<T> del = this;
boolean child = this.left.empty();
boolean child2 = this.right.empty();
right.DelLargest();
if(child && child2)
this.head = null;
else if(child == true && child2 == false)
this.head = left;
}
Basically what I have is that the recursion runs until 'this' is the rightmost node and then checks two cases, whether 'this' is a leaf, or whether 'this' has a left child. (The other case normally associated with this kind of algorithm is redundant because in finding the node with the largest value, I have gone as right as I can go.) The trouble I am having is getting the current node to then either point to null or to the value at Node left.
Note : This is what my instructor referred to as a "modern" Binary search Tree wherein a vertex or "filled" node and a nil or "empty" node are two subclasses of Interface Node which define the characteristics of each type.
I've managed to narrow the problem down to the fact that I do not have a method that returns a value of a given Node. Working on that now, input would be appreciated.
As suggested in the other answer you should use iterative approach.
In a BST the largest value is the rightmost node.
So do a scan and keep going right until you hit a null.
In the scan keep track of three nodes. (gpnode, pnode, node).
Once the scan is done you will have (gpnode,pnode,null)
Now there are 2 cases.
case 1:
pnode is a leaf. So change the edge (gpnode,pnode) to (gpnode,null)
case 2: (EDITED)
pnode.lChild is not null. Note that pnode.rChild will be null as the search would have terminated at that point.
Now change the edge (gpnode,pnode) to (gpnode,pnode.lChild)
Here is the pseudo code:
public class Node
{
long key;
Node lChild;
Node rChild;
}
public void DelLargest()
{
Node gpnode = null;
Node pnode = null;
Node node = root;
while(node != null) // keep going right until a null is reached
{
gpnode = pnode;
pnode = node;
node = node.rChild;
}
if(pnode.lChild == null) // its a leaf node So change the edge (gpnode,pnode) to (gpnode,null)
{
if(gpnode.lChild == pnode)
{
gpnode.lChild = null;
}
else
{
gpnode.rChild = null;
}
}
else // copy lChild's key to this node and delete lChild
{
if(gpnode.lChild == pnode)
{
gpnode.lChild = pnode.lChild;
}
else
{
gpnode.rChild = pnode.lChild;
}
}
}
You've got the right idea. What you want to do is keep a reference to the right most nodes parent, and the right most nodes left child so then when you delete it you can attach the two.
Here's an iterative solution. This will generally be more efficient than recursion, but if you want recursion you should be able to adapt it:
public void delLargest() {
// get rightmost node's parent
Node<T> current = root;
while(current.right != null && current.right.right != null) {
current = current.right;
}
// get the rightmost nodes left node
Node<T> left = current.right.left;
// attach the parent and left
current.right = left;
// nothing points to the right most node anymore, so it will be garbage collected
}

How to get depth of a node in one recursive search in non-binary tree

According to Recursive search for a node in non-binary tree, I know how to achieve the recursive search but how can I get the depth of this node?
I think I should add a counter for every recursion but I have no idea where I should add this counter.....
Thank you
Here is the partial code with comments:
public class Tree
{
private Node root;
public int findDepth(int searchNodeValue) {
List<Node> nodesAtCurrentLevel = Collections.singletonList(root);
return recursiveSearch(0, searchNodeValue, nodesAtCurrentLevel);
}
public int recursiveSearch(int level, int searchNodeValue, List<Node> nodesAtCurrentLevel) {
List<Node> nodesAtNextLevel = new ArrayList<Node>();
// Check if searchNode matches any node at current level
for (Node node : nodesAtCurrentLevel) {
// If it matches, we have found the node, return current level
if (node.getValue() == searchNodeValue) {
return level;
}
// Add children of all nodes at current level in nodesAtNextLevel
if (node.hasChildren()) {
nodesAtNextLevel.addAll(node.getChildren());
}
}
// searchNode is not found at current level, increment level and continue search at next level if next level exists in tree
if (!nodesAtNextLevel.isEmpty()) {
return recursiveSearch(level + 1, searchNodeValue, nodesAtNextLevel);
}
// We have traversed entire tree. Node not found. Return -1
return -1;
}
}
class Node
{
private int value;
private List<Node> children = new ArrayList<Node>();
public Node(int value) {
this.value = value;
}
public boolean hasChildren() {
return children.isEmpty();
}
public int getValue() {
return value;
}
public List<Node> getChildren() {
return children;
}
}
Edited
-- Have the recursion function get a input level. Start with 0/-1. Return a object; the object has the node AND the level. Each pass of recursion function increments the passed in level and sets that in the return object.
-- Pass in the level to recursion function. Start it at 0/-1. Maintain a global variable (or a variable that is defined non local to the function so that the same variable is accessed on each iteration of the function; i.e. the variable is NOT on stack but on heap. I hope this thing is trivial to do in Java and does NOT require further explanation). Set it to (1 + passed in level) at beginning of recursion function. This would NOT be thread safe.
// the original answer had the idea to pass in the level as reference and increment it inside the recursion function. Apparently that is tedious to do in Java.

java alogrithm: find pre/next leaf node that meet special condition from any node in a tree

I need to write a function to find previous/next leaf node that meet special condition from any node in a singly rooted tree. (in the parent first order)
The API would be something like this:
Node findNextLeafNode(Node currentNode, Condition condition);
Node findPretLeafNode(Node currentNode, Condition condition);
where currentNode is any node in a tree, and Node is defined as:
interface Node{
/** #return the Node's parent or null if Node is root */
Node getParent();
/** #return true if node is root */
boolean isRoot();
/** #return non-null array of child nodes (zero length for leaf nodes) */
Node[] getChildren();
/** #return the number of child nodes. If node is leaf, value is 0 */
int getChildCount();
}
And the Condition interface defines the semantics of checking a constraint against a given Node.
interface Condition{
/** #return true if provided node meets the condition */
boolean check(Node node);
}
My question:
Is there an existing library or algorithm for such a common scenario? I am open to either stack based or recursive algorithms. Pseudocode, links to open source libraries, or if you care to share you own code, would be appreciated.
(If not, I need to spend time to invent the same wheel again and paste it here later for sharing.)
Thanks.
-----------------------------write a method to getNext()........
// currentNode must be descendant of root
public static Node getNextNode(Node currentNode, Node root)
{
// 1. if is has child, next is its first child
if (currentNode.getChildSize() > 0) {
return currentNode.getChildren()[0];
}
// 2. if it has no child, check if its is the last child of his parent
else {
// if it is root and has no children, return null
if (currentNode == root) {
return null;
}
// else should have parent which is or under root;
Node parent = currentNode.getParent();
int index = getIndex(currentNode);
if (!isLastofParent(currentNode)) {
// ----a. if not last, next is his parent's next
return currentNode.getParent().getChildren()[index + 1];
}
else {
// ----b. if it is the last one, return its parent's next right if there is. while until root
Node tmp = parent;
while (tmp != root) {
int parentIndex = getIndex(tmp);
if (!isLastofParent(tmp)) {
return tmp.getParent().getChildren()[parentIndex + 1];
}
tmp = tmp.getParent();
}
}
}
return null;
}
private static boolean isLastofParent(Node node)
{
if (getIndex(node) == node.getParent().getChildSize() - 1) {
return true;
}
return false;
}
private static int getIndex(Node currentNode)
{
Node parent = currentNode.getParent();
for (int i = 0; i < parent.getChildSize(); i++) {
if (parent.getChildren()[i] == currentNode) {
return i;
}
}
//TODO: error condition handling, will not happen if tree not change
return -1;
}
------------------------a full search is much easier............
public static Node getNextFailNode(Node currentNode, Node root, Condition condition)
{
boolean foundCurrentNode = false;
Stack<Node> stack = new Stack<Node>();
stack.push(root);
while (!stack.isEmpty()) {
Node tmp = stack.pop();
System.out.println("-popup---------" +tmp+ " ");
if (foundCurrentNode && checkCondition(tmp, condition)) {
return tmp;
}
if (tmp == currentNode) {
foundCurrentNode = true;
}
if (tmp.getChildSize() > 0) {
for (int i = tmp.getChildSize() - 1; i >= 0; i--) {
stack.push(tmp.getChildren()[i]);
}
}
}
return null;
}
This maybe way overblown for what you need, but it can support what you want:
There is a graph traversal language: Gremlin. Typically bolted on top of something like Neo4j, but any graph data structure (e.g. a singly rooted directed tree) can be wrapped to support the API. Take a look at Blueprints projects to find out how it is done.
[edit: for something less heavy]
Perhaps JGraphT is what you want. Also take a look at this question on SO. It is not an exact duplicate, but you should find it helpful.
Write an iterator for your tree that can be initialized from any node and uses pre/in/post-order traversal (Of course it should be bi-directional).
This is basically writing one simple algorithm that at least to me seem basic.
Once you have an iterator all you need is to iterate your way to the next node which is a leaf and the condition holds for it.
If you have trouble with any specific part just ask and I'll improve my answer.
Based on the fact that you already have defined your interfaces, and you say the graph-traversal libraries are too heavyweight, you probably should just write it yourself. It would be an absolutely trivial amount of code. (This page contains some code if you need help.)
(One suggestion for your API: don't put a boolean isRoot(); method on Node, that's a waste of bits unless you have a very good reason to do so. The code that builds the tree should just refer to the root node.)

Categories