开发者

inserting nodes into a binary tree in java question

开发者 https://www.devze.com 2023-02-22 03:09 出处:网络
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,

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;
}


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.


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


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.


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


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;
}


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.


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 );
        }
    }
}


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消