3

im coming from c++ to java and i am confused on binary trees with java. is the only way to have a Node class is to make it an inner static class? all the examples i see do this. However, the way im doing it is i have a node class and a binarytree class uses this node class. but i keep getting an error when i try inserting into the tree after the second insert. i get an exception at this line if(dataIn <= nodeIn.getLeft().getData()){

I am confused as to what i did wrong.... here is my code for insert that i have. thanks in advance..

public void insert(int dataIn){
    root = insert(root, dataIn);
}

private Node insert(Node nodeIn, int dataIn){
    if(nodeIn==null){
        nodeIn = new Node(null, null, dataIn);
    }else{
        if(dataIn <= nodeIn.getLeft().getData()){
            nodeIn.setLeft(insert(nodeIn.getLeft(), dataIn));
        }else{
            nodeIn.setRight(insert(nodeIn.getRight(), dataIn));
        }
    }

    return nodeIn;
}
2
  • 1
    Please indicate the exception you're getting, not just where you're getting it. Commented Apr 6, 2011 at 2:02
  • here is the exception im getting Exception in thread "main" java.lang.NullPointerException at tree.BinaryTree.insert(BinaryTree.java:22) at tree.BinaryTree.insert(BinaryTree.java:15) at driver.Driver.main(Driver.java:16) Commented Apr 6, 2011 at 2:05

8 Answers 8

9

Part of the reason it's confusing is that "Node" should not be a parameter to the insert method, you should be calling an insert method defined in node.

So let's say you hold the "Root" node in your "normal code"--let's call it "rootNode" just to be obscure.

Okay, so your code to insert into the tree would be:

rootNode.insert(newValue);

Easy enough.

Now to define that method.

public class Node {
    private int value;
    private Node lower;
    private Node higher;

    public void insert(int newValue) {
        if (newValue < value)
            if(lower == null)
                lower=new Node(value);
            else
                lower.insert(newValue);
        else
            if(higher == null)
                higher=new Node(value);
            else
                higher.insert(newValue);
      }

 // and you'll need a constructor
    public Node(int value) {
        this.value=value;
    }
}

This should read much more clearly. I'm going to hit "Post" then I'm going to edit it and figure out how to easily refractor that evil evil copy & paste code.

On second thought, I'll leave it there because it's more readable. The best fix I can see is to make the nodes an array, then you get:

public class Node {

    private int value;
    private Node[] nodes=new Node[2];
    private final int LOWER=0;
    private final int HIGHER=1;

    public void insert(int newValue) {
        int index=LOWER;
        if (newValue > value)
            index=HIGHER;

        if(nodes[index] == null)
            nodes[index]=new Node(value);
            else
                nodes[index].insert(newValue);
        }
    }

But I won't replace the original because, as I said, it's clearer.

I recommend the refactoring book for more of this. It really does help simplify your code once you really get OO. Passing an object to an otherwise static method (one that doesn't use member variables) is a dead give-away.

With more considerations about @ted's comment and OO--getLeft and getRight shouldn't even be an issue. Neither is necessary outside the abstraction.

In general what you probably need is these methods in Node:

public boolean doesContain(int value) {
     if(value == this.value)
         return true
     else
         return nodes[ this.value < value ? LOWER : HIGHER].doesContain(value);
}

and maybe

public void getValuesSorted(LinkedList l) {
    nodes[LOWER].getValuesSorted(l);
    l.put(value);
    nodes[HIGHER].getValuesSorted(l);
}

Then you don't even need to expose that it's a tree you are dealing with--beter OO abstraction.

Sign up to request clarification or add additional context in comments.

2 Comments

This is good. To harmonize with method names getLeft() and getRight(), I'd suggest naming the instance variables left and right instead of lower and higher.
Yeah @ted, I agree but the names don't matter much--but since this is hard-coded to do numeric values I figured that for demonstration purposes an explicit match between > and higher was better than a quazi-implied match between > and "Left" or "Right", but the tree terminology is well known so left/right is fine.
3

You need to test whether nodeIn.getLeft() == null.

4 Comments

isnt that being tested in the first if statement when its called recursively?
I'm kind of assuming that getData() will return Integer.MAX_VALUE if it's null. But that seems to be it. No, it's not tested before it matters... you're trying to compare it to an int, so you get an exception: nulls and ints can't compare.
@bdares a primitive int can't ever be null. Assigning null to a primitive throws an exception. He isn't comparing a null to an int, he is comparing an int to an int. The test is getLeft() == null, not getLeft().getData() == null. He is getting an exception because he is trying to call a method on getLeft() and getLeft() is returning null.
@Jonathan you are checking if nodeIn is null, but you are never checking if nodeIn.getLeft() returns null in your code above.
1

is the only way to have a Node class is to make it an inner static class? all the examples i see do this.

No.

The Node class doesn't need to be an inner or nested class. (Strictly speaking a "static inner" class is a nested class.)

However, only an inner or nested class can be private. If your Node class is a regular class you are exposing implementation details to (at least) other classes in the same package. This is a bad idea ... and that explains why you see the Node class declared the way it is.

Comments

1

you can use the below code to clear your understanding. Mostly we do not use any other class everything can be done inside a single Node class itself. here is a very basic example which i believe might be helpful... Also when i see you have two methods in which you have only provided data rather than root. Trust me it is better to have root in your main class. reasoning we have it handy where ever we need to cache.

public Node insert(Node root, Node newNode) {
if (root == null) { 
    root = newNode;
} else {
    if(root.data > newNode.data) {
        root.left = insert(root.left, newNode);
    } else {
        root.right = insert(root.right, newNode);
    }
}
return root;

}

directly call this method from any class where you have initialized. here is a sample plz check..

Node root = new Node(10);
    root.insert(root, new Node(5));
    root.insert(root, new Node(3));
    root.insert(root, new Node(6));
    root.insert(root, new Node(1));

Comments

0

Instead of:

if (dataIn <= nodeIn.getLeft().getData()) {

... you want:

if (dataIn < nodeIn.getData()) {

You need to compare the value that is to be inserted with the value at the current node.

I changed the <= sign to a < sign so that duplicates are avoided.

So your code refactored is:

public void insert(int dataIn) {
  root = insert(root, dataIn);
}

private Node insert(Node nodeIn, int dataIn){
  if (nodeIn == null) {
    nodeIn = new Node(null, null, dataIn);
  } else {
    if (dataIn < nodeIn.getData()) {
      nodeIn.setLeft(insert(nodeIn.getLeft(), dataIn));
    } else {
      nodeIn.setRight(insert(nodeIn.getRight(), dataIn));
    }
  }
  return nodeIn;
}

Comments

0

Actually, for a binary tree there is no need to check whether the inserting element is either greater than or left than the parent node. I think there is no need of checking those conditions. We have to take the input from user whether to insert right or left.

Comments

0
public class TreeNode
{
    private int data;
    private TreeNode left;
    private TreeNode right;

    public Tree( )
    {
        data = 0;
        left = null;
        right = null;
    }

    public Tree( int initialInfo, TreeNode initialLeft, TreeNode initialRight )
    {
        data = initialInfo;
        left = initialLeft;
        right = initialRight;
    }

    public void setLeft( TreeNode newLeft )
    {
        left = newLeft;
    }

    public void setRight( TreeNode newRight )
    {
        right = newRight;
    }

    public void insert( int element )
    {
        if( element <= data )
        {
            if( left == null )
                setLeft( new TreeNode( element, null, null ) );
            else
                left.insert( element );
        }
        else
        {
            if( right == null )
                setRight( new TreeNode( element, null, null ) );
            else
                right.insert( element );
        }
    }
}

Comments

-1

All your solutions do not take into accoount what would happen if the node was to be inserted in the middle of the tree. You are assuming that it will also be smallest or greatest. When you insert something in the middle of the tree, then you will realize that the operation becomes more complex.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.