debugging custom binary tree specific the total(maximum) depth method - java

As for my question: I have a Node class:
public class Node<E> {
private E value;
private Node<E> left;
private Node<E> right;
public Node(E value) {
this.value = value;
this.left = null;
this.right = null;
}
and this class has two methods which calculate the depth of the node (binary tree). The method totaldepth() I wrote myself and it gives an incorrect answer, for which I need your help debugging. The method maxDepth(Node node) gives the correct answer and was used as reference material by me. Could you help me debug totalDepth method as to me it looks the same as maxDepthby the result.
incorrect code:
public int totalDepth() {
// initialize variabele depth
int depth = 0;
// reached leaf return 0
if (right == null && left == null) {
return 0;
}
// not yet reached leaf, continue deeper
else {
int leftdepth = 0;
int rightdepth = 0;
// left node is not null continue going left
if (left != null) {
leftdepth = left.totalDepth();
}
// right node is not null continue going right
if (right != null) {
rightdepth = right.totalDepth();
}
if (leftdepth > rightdepth) {
// 1 is needed because each call to totalDepth raises depth by 1
depth = leftdepth + 1;
}
else {
depth = rightdepth + 1;
}
}
return depth;
}
correct code:
public int maxDepth(Node node) {
if (node == null) {
return (0);
}
else {
// compute the depth of each subtree
int leftDepth = maxDepth(node.left);
int rightDepth = maxDepth(node.right);
// use the larger one
if (leftDepth > rightDepth)
return (leftDepth + 1);
else
return (rightDepth + 1);
}
}
Also I'm just starting to learn how to code so forgive me for all the inefficient things I'm doing. Thanks in advance for helping me!

Your totalDepth method will not work, because you have a tree, and you don't actually know, how many elements you have from the left and the right. Balanced this tree or not. So, only way to walk throw the tree, is to use Breadth-first search or Depth-first search algorithm, and they are based of recursion function like maxDepth(Node node) method.

Related

How to print a subtree of a binary tree?

In my program, I have initialized a binary tree and I want to search if a node exists in that binary tree. If it does exist, then I will print the subtree of that node and the level it was found. I am able to perform my search method but I am not sure how to print the subtree of that node found and its level.
For example, this is my binary tree [K=3 L=[K=1 R=[K=2]] R=[K=5 L=[K=4]]. If I search for node 1, then it will return the node (not null) since it exists in my binary tree.
Problem: I need to print only the subtree of the node and the level where it was found: [K=1 R=[K=2]], level=1.
Here is my source code for reference:
Main Class
// instantiate BST object
BST<Character> bst = new BST<>();
// insert values to bst1
String str = "31254";
char[] letter = str.toCharArray();
for (int i = 0; i < letter.length; i++) {
Character c = letter[i];
bst1.insert(c);
}
// print bst
System.out.println("\nht=" + bst1.height + " " + bst1.toString() + "\n");
// search values in bst1
String str2 = "016483";
char[] letter2 = str2.toCharArray();
for (int i = 0; i < letter2.length; i++) {
Character c = letter2[i];
if (bst1.search(c) != null) { // if found, print the node (w/ subtree) and its level
// ** part that should print the subtree and its level
}
else {
System.out.println(c + " is not found.");
}
}
BST Class - where my search method is declared
public class BST<T extends Comparable<T>> extends BT<T> {
// insert() method
// search method
public BTNode<T> search(T k) {// my method
BTNode<T> n = root;
while (n != null) {
if (n.info.compareTo(k) == 0) {
return n;
}
else {
if (n.info.compareTo(k) > 0) {
n = n.left;
}
else {
n = n.right;
}
}
}
return null;
}
}
Thanks in advance!
I did not modify your code. Instead, I used an imaginary class Node that I've written. Also, I have written all of them as half pseudo half java code.
Suppose your node has only one int type variable and two children.
class Node{
int data;
Node left;
Node right;
}
You have a printExistingSubTree method in your BST class that does the what you exactly ask for:
printExistingSubTree(Node node, int key):
if (find(node.left, key, 0) != -1)
then
printTree(node.left)
print(find(node.left, key, 0))
if (find(node.right, key, 0) != -1)
then printTree(node.right)
printTree(node.right)
print(find(node.right, key, 0))
You have a find method in your BST class that does find the index:
int find(Node node,int key, int level)
if(node.data is equal to the key)
then return level
int left = -1;
if(node.leftChild is not null)
then left = find(node.left, key, level+1)
if(left != -1)
return left
int right = -1;
if(node.rightChild is not null)
then right = find(node.right, key, level+1)
return right
Then, to print, you should decide how you want to traverse the subtree.
You have a printTree method in your BST class that prints the subtree in postorder:
void printTree(Node node){
if (node == null)
return;
printTree(node.left);
printTree(node.right);
print(node.data + " ");
}
Note: I did not understand your whole code. Therefore, I have just written the answer of your question in the pseudo code format. I think, you can write your own code from that.
Note2: There may be some typos&wrong namings. PLease do not lynch. Just write in the comments and I'll correct.

BST - counting nodes with left and right children

As stated in the title, I'm trying to solve this problem by only counting nodes in a BST that have both left and right children. I'm struggling to think of the logic to solve this.
I thought of something like this.
First, check if the root is null or if it has any null children. Next, traverse the tree going right and continue to check the children, increment a counter when the conditions are met. But what happens when I reach the end node and need to go back to a node that had a left child to traverse? I had a temp node to keep track of the most previous parent, but what about when I need to go up more than one level? I'm assuming the answer to this problem is to recursively solve it, but I don't even know where to begin.
Here's what I have:
public int fullNodes() {
int count = 0;
Node n = root;
Node temp = null;
if (n == null || n.left == null && n.right == null) return count;
count++; //increment count, since the root has children on both sides
temp = n; //hold the previous place
n = n.right; //go right
//Now what?
return count;
}
I'm still struggling to think recursively when problem solving, in addition to my question, how do you learn to think recursively? Just a ton of practice, or is there some tricks and tips that you use to solve problems?
Rather than using a temp variable to hold the previous node -- which would only work for a depth of 1 -- call the same function on the child nodes.
Recursive tree traversal might look something like this:
public int countSomething (Node node) {
// Self;
//
int result = 1; // use your required logic here
// Children;
//
if (node.left != null)
result += countSomething( node.left);
if (node.right != null)
result += countSomething( node.right);
// done.
return result;
}
// example usages
int treeTotal = countSomething( rootNode);
int subtreeTotal = countSomething( subtree);
The execution callstack will then hold recursive invocations of the function, each with their appropriate context. When the top-level call returns, it will have summed the answer for the entire tree/ or subtree it was called on.
Put appropriate logic for your BST "node has both left & right children" in, instead of the constant 1.
First let us create representation of your Node class
class Node {
public Node left;
public Node right;
public Node(){}
public Node(Node left, Node right) {
this.left = left;
this.right = right;
}
}
Then we write our recusrive function and client that uses your function
public class Main {
public static int countNodes(Node root) {
if(root!=null && root.left!=null && root.right!=null) {
return 1+countNodes(root.left)+countNodes(root.right);
}
return 0;
}
public static void main(String[] args) {
Node right = new Node();
Node left = new Node();
Node root = new Node(left, right);
root.right = new Node(new Node(), new Node());
System.out.println(countNodes(root));
}
}

Recursively count the number of leaves in a binary tree without given parameters

I am struggling to figure out how to code a recursive algorithm to count the number of leaves in a Binary Tree (not a complete tree). I get as far as traversing to the far most left leaf and don't know what to return from there. I am trying to get the count by loading the leaves into a list and getting the size of that list. This is probably a bad way to go about the count.
public int countLeaves ( ) {
List< Node<E> > leafList = new ArrayList< Node<E> >();
//BinaryTree<Node<E>> treeList = new BinaryTree(root);
if(root.left != null)
{
root = root.left;
countLeaves();
}
if(root.right != null)
{
root = root.right;
countLeaves();
}
if(root.left == null && root.right == null)
{
leafList.add(root);
}
return();
}
Elaborating on #dasblinkenlight idea. You want to recursively call a countleaves on root node & pass back the # to caller. Something on the following lines.
public int countLeaves() {
return countLeaves(root);
}
/**
* Recursively count all nodes
*/
private static int countLeaves (Node<E> node) {
if(node==null)
return 0;
if(node.left ==null && node.right == null)
return 1;
else {
return countLeaves(node.left) + countLeaves(node.right);
}
}
Edit: It appears, a similar problem was previously asked counting number of leaf nodes in binary tree
The problem with your implementation is that it does not restore the value of member variable root back to the state that it had prior to entering the method. You could do it by storing the value in a local variable, i.e.
Node<E> oldRoot = root;
... // your method goes here
root = oldRoot;
However, a better approach is to take Node<E> as an argument, rather than relying on a shared variable:
public int countLeaves() {
return countLeaves(root);
}
private static int countLeaves (Node<E> node) {
... // Do counting here
}

Height of 2-3-4 tree

I have a working snippet to use for a regular tree comprising nodes. Now I just need to fiddle with it to work for 2-3-4 trees, which should be easier, since each path is the same distance, since it's balanced, right?
Methods I have at my disposal include getNextChild(), split(), and of course insert().
public int height() {
return (height(root));
}
private int height(TNode localRoot) {
if(localRoot == null) {
return 0;
}
else {
//Find each sides depth
int lDepth = height(localRoot.leftChild);
int rDepth = height(localRoot.rightChild);
//Use the larger of the two
return (Math.max(lDepth, rDepth) + 1);
}
}
public int height ()
{
TNode cur = root;
int depth = -1;
while ( cur != null )
{
cur = cur.getChild( 0 );
depth++;
}
return depth;
}
If it's balanced, you should just be able to recurse down one side of the tree to determine the height.

Counting nodes in a tree in Java

First of all, I swear this is not homework, it's a question I was asked in an interview. I think I made a mess of it (though I did realise the solution requires recursion). Here is the question:
Implement the count() method which returns the number of nodes in a tree. If a node doesn't have either a left or right child, the relevant getXXChild() method will return null
class Tree {
Tree getRightChild() {
// Assume this is already implemented
}
Tree getLeftChild() {
// Assume this is already implemented
}
int count() {
// Implement me
}
}
My reason for asking the question is simply curious to see the correct solution, and thereby measure how bad mine was.
Cheers,
Tony
int count() {
Tree right = getRightChild();
Tree left = getLeftChild();
int c = 1; // count yourself!
if ( right != null ) c += right.count(); // count sub trees
if ( left != null ) c += left.count(); // ..
return c;
}
A trivial recursive solution:
int count() {
Tree l = getLeftTree();
Tree r = getRightTree();
return 1 + (l != null ? l.count() : 0) + (r != null ? r.count() : 0);
}
A less trivial non-recursive one:
int count() {
Stack<Tree> s = new Stack<Tree>();
s.push(this);
int cnt = 0;
while (!s.empty()) {
Tree t = s.pop();
cnt++;
Tree ch = getLeftTree();
if (ch != null) s.push(ch);
ch = getRightTree();
if (ch != null) s.push(ch);
}
return cnt;
}
The latter is probably slightly more memory-efficient, because it replaces recursion with a stack and an iteration. It's also probably faster, but its hard to tell without measurements. A key difference is that the recursive solution uses the stack, while the non-recursive solution uses the heap to store the nodes.
Edit: Here's a variant of the iterative solution, which uses the stack less heavily:
int count() {
Tree t = this;
Stack<Tree> s = new Stack<Tree>();
int cnt = 0;
do {
cnt++;
Tree l = t.getLeftTree();
Tree r = t.getRightTree();
if (l != null) {
t = l;
if (r != null) s.push(r);
} else if (r != null) {
t = r;
} else {
t = s.empty() ? null : s.pop();
}
} while (t != null);
return cnt;
}
Whether you need a more efficient or a more elegant solution naturally depends on the size of your trees and on how often you intend to use this routine. Rembemer what Hoare said: "premature optimization is the root of all evil."
I like this better because it reads:
return count for left + count for rigth + 1
int count() {
return countFor( getLeftChild() ) + countFor( getRightChild() ) + 1;
}
private int countFor( Tree tree ) {
return tree == null ? 0 : tree.count();
}
A little more towards literate programming.
BTW, I don't like the getter/setter convention that is so commonly used on Java, I think a using leftChild() instead would be better:
return countFor( leftChild() ) + countFor( rightChild() ) + 1;
Just like Hoshua Bloch explains here http://www.youtube.com/watch?v=aAb7hSCtvGw at min. 32:03
If you get it rigth your code reads...
BUT, I have to admit the get/set convention is now almost part of the language. :)
For many other parts, following this strategy creates self documenting code, which is something good.
Tony: I wonder, what was your answer in the interview.
return (getRightChild() == null ? 0 : getRightChild.count()) + (getLeftChild() == null ? 0 : getLeftChild.count()) + 1;
Or something like that.
Something like this should work:
int count()
{
int left = getLeftChild() == null ? 0 : getLeftChild().count();
int right = getRightChild() == null ? 0 : getRightCHild().count();
return left + right + 1;
}
class Tree {
Tree getRightChild() {
// Assume this is already implemented
}
Tree getLeftChild() {
// Assume this is already implemented
}
int count() {
return 1
+ getRightChild() == null? 0 : getRightChild().count()
+ getLeftChild() == null? 0 : getLeftChild().count();
}
}
You can count the tree by traversing it many ways. Simply preorder traversal, the code would be (based on the functions you defined):
int count() {
count = 1;
if (this.getLeftChild() != null)
count += this.getLeftChild().count();
if (this.getRightChild() != null)
count += this.getRightChild().count();
return count;
}
Implement the method:
public static int countOneChild(Node root)
{
...
}
that counts the number of internal nodes in a binary tree having one child. Add the function to tree.java program.
I did it by preorder recurssion. Altough it doesn't exactly follow the interview format by using localRoot, but I think you get the idea.
private int countNodes(Node<E> localRoot, int count) {
if (localRoot == null)
return count;
count++; // Visit root
count = countNodes(localRoot.left, count); // Preorder-traverse (left)
count = countNodes(localRoot.right, count); // Preorder-traverse (right)
return count;
}
public int countNodes() {
return countNodes(root, 0);
}
This is a standard recursion problem:
count():
cnt = 1 // this node
if (haveRight) cnt += right.count
if (haveLeft) cnt += left.count
return cnt;
Very inefficient, and a killer if the tree is very deep, but that's recursion for ya...
int count()
{
int retval = 1;
if(null != getRightChild()) retval+=getRightChild().count();
if(null != getLeftChild()) retval+=getLeftChild().count();
return retval;
}
God I hope I didn't make a mistake.
EDIT: I did actually.
Of course, if you want to avoid visiting every node in your tree when you count, and processing time is worth more to you than memory, you can cheat by creating your counts as you build your tree.
Have an int count in each node,
initialized to one, which
respresents the number of nodes in
the subtree rooted in that node.
When you insert a node, before
returning from your recursive insert
routine, increment the count at the
current node.
i.e.
public void insert(Node root, Node newNode) {
if (newNode.compareTo(root) > 1) {
if (root.right != null)
insert(root.right, newNode);
else
root.right = newNode;
} else {
if (root.left != null)
insert(root.left, newNode);
else
root.left = newNode;
}
root.count++;
}
Then getting the count from any point just involves a lookup of node.count
My first attempt didn't have anything new to add, but then I started to wonder about recursion depth and whether it would be possible to rearrange the code to take advantage of the tail call optimization feature of the latest Java compiler. The main problem was the null test - which can be solved using a NullObject. I'm not sure if TCO can deal with both recursive calls, but it should at least optimize the last one.
static class NullNode extends Tree {
private static final Tree s_instance = new NullNode();
static Tree instance() {
return s_instance;
}
#Override
Tree getRightChild() {
return null;
}
#Override
Tree getLeftChild() {
return null;
}
int count() {
return 0;
}
}
int count() {
Tree right = getRightChild();
Tree left = getLeftChild();
if ( right == null ) { right = NullNode.instance(); }
if ( left == null ) { left = NullNode.instance(); }
return 1 + right.count() + left.count();
}
The precise implementation of NullNode depends on the implementations used in Tree - if Tree uses NullNode instead of null, then perhaps the child access methods should throw NullPointerException instead of returning null. Anyway, the main idea is to use a NullObject in order to try to benifit from TCO.
Questions related to binary tree should be expected in an interview. I would say to take time before any next interview and go through this link. There are about 14 problems solved .You can have a look and how the solution is done. This would give you an idea of how to tackle a problem with binary tree in future.
I know your question is specific to the count method .That is also implemented in the link that i provided
class Tree {
Tree getRightChild() {
// Assume this is already implemented
}
Tree getLeftChild() {
// Assume this is already implemented
}
int count() {
if(this.getLeftChild() !=null && this.getRightChild()!=null)
return 1 + this.getLeftChild().count() + this.getRightChild().count();
elseif(this.getLeftChild() !=null && this.getRightChild()==null)
return 1 + this.getLeftChild().count();
elseif(this.getLeftChild() ==null && this.getRightChild()!=null)
return 1 + this.getRightChild().count();
else return 1;//left & right sub trees are null ==> count the root node
}
}

Categories