Recurse within binary tree's node class - java

I have successfully written a method to print the values of all the nodes in the subtree rooted at a given node (code pasted below under the label "Working Code"). However, this printTree method is in the Main class (as opposed to being in the Node class itself). I am wondering if it is possible (and ideal?) to rewrite the code so that the printTree method is in the Node class itself? My attempt is below (code pasted below under the label "Non Working Code"), but it threw a Null Pointer Exception. Thank you!
WORKING CODE:
public class Node {
int value;
Node left;
Node right;
public Node(int value, Node left, Node right)
{
this.value = value;
this.left = left;
this.right = right;
}
}
public class Main {
public static void printTree(Node current)
{
if (current != null)
{
System.out.println(current.value);
printTree(current.left);
printTree(current.right);
}
return;
}
public static void main(String[] args) {
// write your code here
Node a = new Node(3, new Node(4, null, null), new Node(5, null, null));
printTree(a);
}
}
NON WORKING CODE (in Node class):
public void printTree()
{
Node current = this;
if (current != null)
{
System.out.println(current.value);
current.left.printTree();
current.right.printTree();
}
return;
}

The problem is not in the Node current = this; line. But in the
current.left.printTree();
current.right.printTree();
lines.
Because even when current is not null, current.left or current.right could be null. And you are trying to invoke printTree() on a null object.
Fix:
if (current != null)
{
System.out.println(current.value);
if (current.left != null)
current.left.printTree();
if (current.right != null)
current.right.printTree();
}

Related

Best practice to build a BST from a Binary Tree

Im creating a Binary Search Tree in Java extending from a Binary Tree already implemented, but it does not work when I try to use some inherited methods. Let me explain:
Binary Tree:
public class BinaryTree<T>{
private Node<T> root;
public class Node<T>{
T value;
Node left;
Node right;
public Node(T value){
this.value = value;
this.left = null;
this.right = null;
}
}
public BinaryTree(){
...
}
public void printInOrder(){
...
}
}
BST:
public class BST extends BinaryTree<Integer>{
private Node<Integer> root;
public BST(Integer v){
super(v);
}
public void insert(Integer element){
insert(this.root, element);
}
private insert( Node node, Integer element){
if(node == null)
return;
if(node.value > value) {
if(node.left != null) {
insert(node.left, value);
}
else {
node.left = new NodeBST(value);
}
}else { // Node.value < element
if(node.right != null) {
insert(node.right, value);
}
else {
node.right = new NodeBST(value);
}
}
}
}
App:
public class App{
public static void main(String[] args){
BST bst = new BST(4);
bst.insert(2);
bst.insert(5);
bst.insert(3);
bst.insert(7);
bst.printInOrder(); //Here I got the problem
}
}
If I try to print it, it will just print the root (4) and will be null for the rest of the nodes. When I look what's going on inside, it turns out there is two roots:
BST.Node root, which contains all the nodes in the proper order
BinaryTree.Node root, which just contains the root and all the other nodes are null.
So I guess it creates the root correctly because I'm calling the super class in the BST' constructor, but when I creates a new Node in the insert method, it only appends it in BST.Node root (and not in the BinaryTree.Node root), therefore when I call print, which is implemented in BinaryTree, from BST in prints null :/
So my questios are:
How can I get to use the print method from BST in order to print all the values in BST.Node root?
What does prevent BinaryTree.Node root to be the same as BST.Node root?
What would be the best practice to do so?
Don't declare 'root' a second time in BST, it shadows the 'root' in the base class.
Either make 'root' in BinaryTree protected or provide the necessary accessors there, so subclasses can use it.

How make an add Method with a BinarySearchTree in Java?

I am having trouble with my add method, I believe that the error occurs in the parameters passed in the public method, however I'm not sure if my private helper method is also not adding the correct variables.
Here are the instructions to my addMethod
The add(E) method may additionally call the assignFirst() method to assign the first attribute in case it should be changed. The add helper method should now assign each node's "parent" and "next" references when a new node is created.
• The "parent" parameter should reference a newly created node's parent node, so when
creating a new node, you can simply assign its parent to this parameter.
• The "prev" parameter should reference a newly created node's previous node, so when
creating a new node, you can simply update the "next" references in the appropriate
nodes. The tricky part is knowing what values to pass when you're calling the add
helper method. Here's the logic:
• If the add helper return value is to be a right child, then that right child's previous
node should be the same as its parent. The optional getPrevNode won't be helpful
here since the previous node will be the new node's parent, and the new node isn't
yet attached to the tree.
• If the add helper return value is to be a left child, then that left child's previous node
could be determined by the optional getPrevNode method, asking it for the node that
is before the current node parameter.
Here is my code:
public void add(E value)
{
this.root = add(root, value, root, null);
assignFirst();
}
// post: value added to tree so as to preserve binary search tree
private BSTNode<E> add(BSTNode<E> node, E value, BSTNode<E> parent, BSTNode<E> prev)
{
if (node == null)
{
node = new BSTNode<E>(value);
node.parent = parent;
node.next = prev;
this.numElements++;
}
else if (node.data.compareTo(value) > 0)
{
node.left = add(node.left, value, node , getPrevNode(node));
}
else if (node.data.compareTo(value) < 0)
{
node.right = add(node.right, value, node, node.parent);
}
return node;
}
private void assignFirst()
{
BSTNode<E> node = root;
while(node.left != null)
{
node = node.left;
}
first = node;
}
private BSTNode<E> getPrevNode(BSTNode<E> node)
{
if(node.left != null)
{
node = node.left;
while(node.right != null)
{
node = node.right;
}
return node;
}
else if(node.parent != null)
{
if(node.parent.right == node)
{
return node.parent;
}
if(node.parent.left == node)
{
while(node.parent != null && node.parent.left == node)
{
node = node.parent;
}
if(node == root)
{
return null;
}
else
{
return node.parent;
}
}
}
return null;
}
Here is some background information, however I'm leaving some methods out since they're irrelevant to what I am trying to figure out. Therefore I am cutting it short.
public class BinarySearchTree<E extends Comparable<E>>
{
private BSTNode<E> root; // root of overall tree
private int numElements;
private BSTNode<E> first;
// post: constructs an empty search tree
public BinarySearchTree()
{
this.root = null;
this.numElements = 0;
}
public class Iterator
{
private BSTNode<E> currentNode;
public Iterator()
{
currentNode = first;
}
public boolean hasNext()
{
return currentNode != null;
}
public E next()
{
E value = currentNode.data;
currentNode = currentNode.next;
return value;
}
}
private static class BSTNode<E>
{
public E data;
public BSTNode<E> left;
public BSTNode<E> right;
public BSTNode<E> parent;
public BSTNode<E> next;
public BSTNode(E data)
{
this(data, null, null, null, null);
}
public BSTNode(E data, BSTNode<E> left, BSTNode<E> right, BSTNode<E> parent, BSTNode<E> next)
{
this.data = data;
this.left = left;
this.right = right;
this.parent = parent;
this.next = next;
}
}
}
This was a rigorous process, here's what I got
public void add(E value)
{
this.root = add(root, value, root, null);
assignFirst();
}
// post: value added to tree so as to preserve binary search tree
private BSTNode<E> add(BSTNode<E> node, E value, BSTNode<E> parent, BSTNode<E> prev)
{
if (node == null)
{
node = new BSTNode<E>(value);
node.parent = parent;
if(prev == null)
{
node.next = parent;
}
else
{
node.next = prev.next;
prev.next = node;
}
this.numElements++;
}
else if (node.data.compareTo(value) > 0)
{
node.left = add(node.left, value, node , getPrevNode(node));
}
else if (node.data.compareTo(value) < 0)
{
node.right = add(node.right, value, node, node);
}
return node;
}

Cannot cast from inner class to class

I have a BinaryTree class which contains an inner class Node.
What I would like to do is to be able to insert some nodes in my BinaryTree tree by calling tree.insert(node). However, to keep it clean and consistent, I dont want to create an insert() method inside Node inner class. So I tried the code below, but I have an error: Cannot cast from BinaryTree.Node to BinaryTree.
What should I do?
BinaryTree class
public class BinaryTree {
Node root = null;
private class Node {
int value;
Node left;
Node right;
}
public BinaryTree(int v) {
root.value = v;
root.left = null;
root.right = null;
}
public void insert(Node n) {
/* Error */
if(n.value > root.value) ((BinaryTree) root.right).insert(n);
}
}
Main class
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
String[] str = sc.nextLine().split(" ");
BinaryTree tree;
for(int i = 0; i < str.length-1; i++) {
int val = Integer.parseInt(str[i]);
//tree.insert(node);
}
}
}
Thanks,
You don't need typecasting inside insert method. It should be like this:
public void insert(Node n) {
if(n.value > root.value)
insert(root.right);
}
To insert a node in a tree you need to define where to insert it, so your insert methods should be something like:
//insert a new node right to a node. not null safe
public void insert(Node newNode, Node rightTo) {
newNode.right = rightTo.right;
newNode.left = rightTo;
rightTo.right = newNode;
}
which does not require casting.
To find the rightTo node you could use:
//get the last node which has a value lower than `value`
//may return null
public Node getNodeWithValueLowerThan(int value) {
if(root == null) return null;
return getNodeWithValueLowerThan(root, value);
}
//recursive method. null safe
private Node getNodeWithValueLowerThan(Node node, int value) {
if(node == null) return null;
if(node.value > value) return node.left; //return previous node. may be null
return getNodeWithValueLowerThan(node.right, value);
}
To insert a node as a last node, you could use:
//insert a new node as last
public void insertLastNode(Node newNode) {
Node lastNode = getTail();
if(lastNode == null) {//empty tree
root = newNode;
return;
}
newNode.left = lastNode;
lastNode.right = newNode;
}
where getTail is something like:
//find last node
private Node getTail() {
if(root == null) return null;
return getTail(root);
}
//recursive method to find last node. not null safe
private Node getTail(Node node) {
if(node.right == null) return node;
return getTail(node.right);
}
Note: code was not tested so debug carefully.

Binary tree with add a node at a specific existing node

I'm trying to create a binary tree in Java to model the way in a perfect maze.
Each node Node<T> can have 2 children (Node<T> left and Node<T> right).
Each node is definited with T data as (x,y) coordinates.
For add a new node, I need to find the actual node (current position) :
previousPosition = actualPosition;
move();
tree.addNode(previousPosition, actualPosition);
And addNode must me search the node previousPosition for add a child (actualPosition) to left or rigth (depending of null child).
I need your help.
My code:
public class BinaryTree<T> {
// Root node pointer. Will be null for an empty tree.
private Node root;
/*
--Node--
The binary tree is built using this nested node class.
Each node stores one data element, and has left and right
sub-tree pointer which may be null.
The node is a "dumb" nested class -- we just use it for
storage; it does not have any methods.
*/
private static class Node<T> {
Node<T> left;
Node<T> right;
T data;
Node(T newData) {
left = null;
right = null;
data = newData;
}
}
...
...
...
private Node<T> insert(Node<T> node, T parent, T data) {
if(node.data.equals(parent)) {
if(node.left == null) {
node.left = new Node<T>(data);
} else if (node.right == null) {
node.right = new Node<T>(data);
} else {
System.out.println("Children are not nulls");
}
} else {
if(node.left != null) {
insert(node.left, parent, data);
}
if(node.right != null) {
insert(node.right, parent, data);
}
}
return node;
}
}

get root of a binary search tree in java

I have created a binary search tree in java that allow user to add nodes to the tree
This is my implementation of the binary tree in java which accept root node on creation and then automatically figure out that it should add the child into left side or right side of the tree.
public class BinarySearchTree {
Node root = null;
public BinarySearchTree(Node root){
this.root =root;
}
public void add(int data){
Node newNode = new Node(data);
if(this.root ==null){
newNode =this.root;
}
if(data>this.root.data){
addRight(root,newNode);
}
if(data<this.root.data){
addLeft(root,newNode);
}
}
public Node getRoot(){
return this.root;
}
private void addLeft(Node root, Node newNode) {
if(root.leftChild == null){
root.leftChild = newNode;
}
else {
this.root = this.root.leftChild;
add(newNode.data);
}
}
private void addRight(Node root,Node newNode) {
if (root.rightChild == null){
root.rightChild = newNode;
}
else {
this.root = this.root.rightChild;
add(newNode.data);
}
}
}
But when I try to retrieve the root node with getRoot() method. it return me the child of the root rather than the actual root node that I had passed in.
this is a example of using it
TreeHight treeHight = new TreeHight();
Node root = new Node(100);
BinarySearchTree unbalance = new BinarySearchTree(root);
unbalance.add(200);
unbalance.add(50);
unbalance.add(250);
unbalance.add(350);
when I try to get root node it give me 250 as the first node rather than 100.
How can I retrieve the root node of this tree ?
In your code you write:
this.root = this.root.leftChild;
add(newNode.data);
This is probably wrong behavior?
You should rewrite it to:
add(this.root.leftChild,newNode);
And then define a recursive method that looks whether the item should be stored left/right of the subroot.
Something like:
public void add(Node subroot, int data){
if(data > subroot.data){
addRight(subroot,data);
}
else if(data < subroot.data){
addLeft(subroot,newNode);
}
}
private void addLeft(Node subroot, int data) {
if(subroot.leftChild == null){
subroot.leftChild = new Node(data);
}
else {
add(subroot.leftChild,data);
}
}
private void addRight(Node subroot, int data) {
if(subroot.rightChild == null){
subroot.rightChild = new Node(data);
}
else {
add(subroot.rightChild,data);
}
}
And the add method is then:
public void add(int data){
if(this.root == null){
this.root = new Node(data);
}
else {
this.add(this.root,data);
}
}
I think an invariant of a binary tree is that the root remains the same. The same goes for addRight by the way.
Finally you also wrote:
newNode =this.root;
in your add method, this of course, doesn't make much sense.
You are editing the root in this line:
this.root = this.root.rightChild;
I think you should add the new node to the right recursively like this:
else {
addRight(this.root.rightChild, newNode);
}
And just as a note i think you have problem in this block "in the add method":
if(this.root ==null){
newNode =this.root; // it should be this.root = newNode;
}

Categories