Matt Andrzejczuk
Matt Andrzejczuk

Reputation: 2066

Counting the nodes in a binary search tree

I need to create a recursive method that takes as a parameter the root node of a binary search tree. This recursive method will then return the int value of the total number of nodes in the entire binary search tree.

This is what I have so far:

public class BinarySearchTree<E> extends AbstractSet<E>
{
protected Entry<E> root; 


//called by the main method
public int nodes()
{
    return nodes(root);
}       

//nodes() will count and return the nodes in the binary search tree

private int nodes(Entry<E> current)
{    
    if(current.element != null)
    { 
        if(current.left == null && current.right == null)
        {
            if(current.element == root.element)
            return 1;                   

            deleteEntry(current);              
            return 1 + nodes(current.parent);
        }
        else if(current.left != null && current.right == null)        
            return nodes(current.left);

        else if(current.left == null && current.right != null)
            return nodes(current.right);

        else if(current.left != null && current.right != null)
            return nodes(current.left) + nodes(current.right);      
    } else return 1;
    return 0;
}

The main method calls nodes like so:

        System.out.println ("\nThis section finds the number of nodes "
             + "in the tree"); 

        System.out.println ("The BST has " + bst.nodes() + " nodes");

So I was running the search by traveling in order, once I'd get to a node with no children I would delete the current node and return to the parent node and continue. I ran a debug of the method I have above and the program crashes with a NullPointerException() when it finally counts and removes all the nodes on the left and right side of the root node and tries to return 1.

This is for my lab, the method MUST be recursive.

I'm very lost at this point, does anyone know what I'm doing wrong?

Upvotes: 2

Views: 34706

Answers (5)

Antoniet Ama Aggrey
Antoniet Ama Aggrey

Reputation: 21

public int countNodes(Node root){
    // empty trees always have zero nodes
    if( root == null ){
        return 0;
    }

    // a node with no leafes has exactly one node
    // note from editor: this pice of code is a micro optimization
    // and not necessary for the function to work correctly!
    if( root.left == null && root.right == null ){
        return 1;
    }

    // all other nodes count the nodes from their left and right subtree
    // as well as themselves
    return countNodes( root.left ) + countNodes( root.right ) + 1;
}

Upvotes: 1

Reinier Maas
Reinier Maas

Reputation: 31

Hey I have a very clean counting implemented for a binary tree:

public class Binary<T> where T: IComparable<T>
{
    private Node _root;

    public int Count => _root.Count;

    public void Insert(T item)
    {
        Node newNode = new Node(item);
        if (_root == null)
            _root = newNode;
        else
        {
            Node prevNode = _root;
            Node treeNode = _root;
            while (treeNode != null)
            {
                prevNode = treeNode;
                treeNode = newNode.Item.CompareTo(treeNode.Item) < 1 ? treeNode.Left : treeNode.Right;
            }
            newNode.Parent = prevNode;
            if (newNode.Item.CompareTo(prevNode.Item) < 1)
                prevNode.Left = newNode;
            else
                prevNode.Right = newNode;
        }
    }

    public class Node
    {
        public T Item;

        public Node Parent;
        public Node Left;
        public Node Right;

        public Node(T item, Node parent = null, Node left = null, Node right = null)
        {
            Item = item;
            Parent = parent;
            Left = left;
            Right = right;
        }

        public int Count
        {
            get
            {
                int count = 1;
                count += Left?.Count ?? 0;
                count += Right?.Count ?? 0;
                return count;
            }
        }
    }
}

Maybe this helps you to understand how to implement a class for a simple binary tree with a count.

This implementation accesses the count through a count in the corresponding node in the tree.

Let me now if you are not familiar with the markup of .NET 4.6

Upvotes: 0

cHao
cHao

Reputation: 86506

You have several issues:

  • You're deleting nodes as you count them? Is nodes() supposed to clear the tree?
  • You're treating root==null, root!=null&left==null&&right==null, root!=null&left!=null&right==null, etc as separate cases. They're not. You have three cases, which are not entirely exclusive:
    • If the current node is not null, add one to the count. (This should always be the case. The only case where it might be false is if the current node == root, and we can detect and sidestep that beforehand.)
    • If the current node has a left child, add the left child's count.
    • If the current node has a right child, add the right child's count.
  • You're traversing back up the tree for some ungodly reason. Looks like it has something to do with deleting nodes...?

But the biggest thing in my opinion is, you're not giving enough autonomy to the Entrys. :P

A node can count its own children. Trust it to.

class Entry<E> {
    ...

    int count() {
        int result = 1;
        if (left != null) result += left.count();
        if (right != null) result += right.count();
        return result;
    }
}

public int nodes() {
    return (root == null) ? 0 : root.count();
}

If your teacher is incompetent, and insists on some node-counting function outside a node, you can do the same thing you were trying to do:

private int nodes(Entry<E> current) {
     int result = 1;
     if (current.left) result += nodes(current.left);
     if (current.right) result += nodes(current.right);
     return result;
}

public int nodes() {
     return (root == null) ? 0 : nodes(root);
}

But that teacher should be fired, in my opinion. The Entry class is the real tree; BinarySearchTree is really just a container for a reference to the root.

Also notice, i don't give a damn about the parents. If we start counting from the root, and each node counts its children, which count their children, etc etc... then all nodes will be accounted for.

Upvotes: 4

durron597
durron597

Reputation: 32323

You are making this way too complicated. The basic idea of object oriented programming is that you trust objects to do the jobs they know the answers to. So if I'm a parent, I can count myself, and I let my children count themselves, and so forth.

private int nodes(Entry<E> current) {   
  // if it's null, it doesn't exist, return 0 
  if (current == null) return 0;
  // count myself + my left child + my right child
  return 1 + nodes(current.left) + nodes(current.right);
}

Upvotes: 17

bhuang3
bhuang3

Reputation: 3633

After you delete current in: deleteEntry(current);, you use current.parent in return 1 + nodes(current.parent);

May be this's the reason of throwing NullPointerException..

Upvotes: 0

Related Questions