-2
class TreeNode {

TreeNode left;
TreeNode right;
char ch;

TreeNode(char ch){
    this.right = null;
    this.left = null;
    this.ch = ch;
}

TreeNode(TreeNode left, TreeNode right, char ch){
    this.left = left;
    this.right = right;
    this.ch = ch;
}
}

public class ExpressionTree {
public TreeNode root;

public void inorder() {
    inorder(root);
}

public void inorder(TreeNode node) {
    if (node != null){
        inorder(node.left);
        System.out.printf(node.ch + " ");
        inorder(node.right);
    }
}

public void preorder() {
    preorder(root);
}

public void preorder(TreeNode node) {
    if (node != null){
        System.out.printf(node.ch + " ");
        preorder(node.left);
        preorder(node.right);
    }
}

public void postorder() {
    postorder(root);
}
public void postorder(TreeNode node) {
    if (node != null){
        postorder(node.left);
        postorder(node.right);
        System.out.printf(node.ch + " ");
    }
}

public int size() {
    int countLeft = 0, countRight= 0;
    TreeNode nodeLeft = this.root.left;
    TreeNode nodeRight = this.root.right;
    if (this.root == null)
        return 0;

    if (this.root.left == null && this.root.right == null)
        return 1;

    while (nodeLeft != null){
        countLeft = countLeft + 1;
        nodeLeft = nodeLeft.left;
    }

    while (nodeRight != null){
        countRight = countRight + 1;
        nodeRight = nodeRight.right;
    }
    return 1 + countLeft + countRight;
}

public int recSize() { return recSize(root); }

public int recSize(TreeNode node) {
    int count = 0;
    if (node == null)
        return 0;
    if (node.left == null && node.right == null){
        return 1;
    }else{
        return 1 + recSize(node.left) + recSize(node.right);
    }
}
}

I am wondering why the iteration ver. is not working to find the number of node in this binary tree? It seems to be able to find the number of leafs only(Please correct me if i am wrong to this statement also).

TszKin Anthony
  • 15
  • 2
  • 10

3 Answers3

1

I think that the issue you are running into with the iterative count of the nodes of your trees is this:

When you reassign nodeLeft to nodeLeft.left, you are only counting the left children of the left node. If the left child of your root has a right child, it will not be counted. The inverse is true for the right child. In effect, the iterative method is only counting the nodes that constitute the leftmost, and rightmost portions of your binary tree

To clarify further, the best way to count the nodes in the tree without directly using recursion is probably to push the left and right child nodes to a stack, add one to your total, pop the next node off of the stack, push that nodes children if it has any, and repeat until the stack is empty.

Something like this should do the trick:

Stack visitStack<TreeNode> = new Stack();
visitStack.push(this.root);
while(!visitStack.isEmpty()){
    count++;
    TreeNode next = visitStack.pop();
    if(next.left != null){
        visitStack.push(next.left);
    }
    if(next.right != null){
        visitStack.push(next.right);
    }
}

Note that there is no way to traverse all of the nodes of the tree using iteration that is quite as elegant as using recursion, since trees are inherently recursive.

Additionally, if you don't care what order you are visiting these nodes in (if you are just counting them, it doesn't seem as though you would) then there is no reason that you couldn't use something along the lines of a queue or a dynamic array or whatever to hold and remove your nodes from in place of a stack.

M. Powell
  • 69
  • 4
  • I implemented the recursive way right below the iterative method. I need both of them. Any suggestion? – TszKin Anthony Nov 14 '16 at 06:38
  • Yes, I saw that. Since it seems like you are in the process of learning about data structures, I just thought I would add the tidbit about why the recursive solution is more elegant. – M. Powell Nov 14 '16 at 06:41
  • Exactly, recursive is much easier to understand and implement. However, it might be troublesome to deal with big trees. (In terms of number of nodes). So..... iterative is still a choose. – TszKin Anthony Nov 14 '16 at 06:46
  • Sure, if you need to go iterative, and you just need to count the nodes, there's nothing special about a stack. You can just use an `ArrayList` instead, and add/remove to and from that. – M. Powell Nov 14 '16 at 06:52
1

The Error The iterative version has a flaw. It does really count only the root, left->left->left->left->... and right->right->right->right->...


Since, you don't have a back pointer to traverse the inner nodes. You have to use a stack to store Nodes.


Program [Iterative Version]

You can use this code to count number of nodes in the tree.

public int size() {
    Stack<TreeNode> s = new Stack<>();
    s.push(root);
    int result=0;
    while(!s.isEmpty())
    {
        TreeNode top = s.peek();
        if(top.left!=null)
        {
            stack.push(top.left);
            top.left=null;
        }  
        else
        {
            result++;
            stack.pop();
            if(top.right!=null)
            {
                stack.push(top.right);
            }
        }
    }
    return result;
}

Program [Recursive Version]

If you shouldn't use stack explicitly you can write recursive code. But, mind you, recursive code implicitly uses a stack.

private int countNodes(TreeNode n)
{
    if(n==null)
        return 0;
    else
    {
        return 1 + countNodes(n.left) + countNodes(n.right);
    }
}

public int size()
{
    return countNodes(root);
}
Tarun Maganti
  • 3,076
  • 2
  • 35
  • 64
  • I am not allowed to use Stack.... I have seen many done by using stack. Thanks anyway. – TszKin Anthony Nov 14 '16 at 06:21
  • In Trees, a node doesn't have the pointer to the parent. You should store your nodes which you have traverse partly. ie., only one child tree has been traversed. For storing elements you can use any collection, but you'll end up using methods similar to push and pop (if they exist in the collection ofcourse). – Tarun Maganti Nov 14 '16 at 06:41
0

Your iterative code doesn't work because it reads a node, goes to its left (or right) and forgets about that node's right (or left) children. You code assumes that every node is having either a right or a left child, and not both (except the root node).

 while (nodeLeft != null){
        countLeft = countLeft + 1;
        nodeLeft = nodeLeft.left; //Missed the right child here
    }
while (nodeRight != null){
        countRight = countRight + 1;
        nodeRight = nodeRight.right; //Missed the left child here
    } 

If you can't use a stack, use a Queue. A breadth-first traversal to traverse all the nodes of the tree. A breadth-first traversal visits a node(N), keeps the children node (N1, N2 ...., in case of Binary Tree, Nl and Nr) which can be reached from that node(N) in queue and removes the node(N) itself from the queue. And similarly goes on, getting a node from queue, adding it's children to queue (if they have not been previously visited) and removing the node from queue.

But if you are looking for a constant space traversal to count the nodes, I would suggest you to look into the following Geeks For Geeks, Constant Space traversal of binary tree.

I won't give the code for breadth-first traversal. I assume that you can cook that up on your own.

AnkitAti
  • 186
  • 1
  • 4
  • 10