Counting nodes in a tree in Java

前端 未结 15 1620
我寻月下人不归
我寻月下人不归 2020-12-03 00:03

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).

相关标签:
15条回答
  • 2020-12-03 00:11

    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...

    0 讨论(0)
  • 2020-12-03 00:15

    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);
    }
    
    0 讨论(0)
  • 2020-12-03 00:17
    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
      }
    }
    
    0 讨论(0)
  • 2020-12-03 00:19

    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;
    }
    
    0 讨论(0)
  • 2020-12-03 00:22

    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."

    0 讨论(0)
  • 2020-12-03 00:23

    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.

    0 讨论(0)
提交回复
热议问题