Best practice to build a BST from a Binary Tree - java

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.

Related

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.

Initiating a binary search tree using a rootNode that is null

I have this node class
public class Node {
Node right;
Node left;
int value;
Node(int value) {
this.value = value;
}
Node insertValue(int v){
if(this == null){
return new Node(v);
}
//Rest of the method
}
}
I want to make a rootNode that is the tree. If it is null, the tree is empty. Edit: The methods to populate the tree, find minimum, etc. must be recursive methods of class Node
class Main{
public static void main(String[] args) {
Node rootNode = null;
rootNode.insertValue(5);
}
}
Of course, since rootNode == null, I can't use it to call insertValue.
I am looking for a way to populate an empty tree(rootNode == null) with inner methods. Any tips on how I can do this?
You can create a new class Tree which contains (only) the root node and methods to work with like insertValue(). The Node class will become more or less a private helper class for the internals of the tree.
public class Tree {
private Node root;
public void insertValue(int v) {}
public int getSize() {}
public int getValue(int index) {}
}

Recurse within binary tree's node class

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

Inserting a node in BST

I am trying to insert nodes in my custom BST.The first time the insertData method is called , the new node is correctly inserted as the root.The problem is occuring in the second and subsequent calls.
Below is My code :
1.The Node Class =
package ishan.trees.tree;
class Node implements Comparable<Node> {
private int data;
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getLeftChild() {
return leftChild;
}
public void setLeftChild(Node leftChild) {
this.leftChild = leftChild;
}
public Node getRightChild() {
return rightChild;
}
public void setRightChild(Node rightChild) {
this.rightChild = rightChild;
}
private Node leftChild;
private Node rightChild;
public Node(int data,Node leftChild,Node rightChild)
{
this.data=data;
this.leftChild=leftChild;
this.rightChild=rightChild;
}
#Override
public int compareTo(Node o) {
if(o.getData() > this.data)
return -1;
if(o.getData() < this.data)
return 1;
return 0;
}
}
The Tree Class =
package ishan.trees.tree;
public class Tree {
private Node root=null;
public Node getRoot() {
return root;
}
public void insertData(int data)
{
Node node=new Node(data,null,null);
insert(node,this.root);
}
private Node insert(Comparable<Node> node,Node root1)
{
if(root1==null)
{//insert as first element ie root
this.root=new Node(((Node)node).getData(),null,null);
}
else if(node.compareTo(root1) <0)
{
root1.setLeftChild(insert(node,root1.getLeftChild()));
}
else if(node.compareTo(root1) >0)
{
root1.setLeftChild(insert(node,root1.getRightChild()));
}
return root1;
}
}
3.Main Class =
package ishan.trees.usage;
import ishan.trees.tree.Tree;
public class Usuage {
public static void main(String a[])
{
Tree tree=new Tree();
tree.insertData(10); //---------1
tree.insertData(15); //---------2
tree.insertData(9); //---------3
tree.insertData(4); //---------4
}
}
when i debug the second call it is something like this:
insertData(15){
insert(15,10)
}
which makes a call to the insert method as ---->
insert(15,null)
I get this null every time and this results in the current node replacing the root node.
I cant figure out why during the call , the root1 reference is null and not pointing to my root?
More Info :
Its during the call from insertData() to insert() . say During my second call to insertData(15) , i make a call to insert(15,this.root) -->insert(node,root1) . but this root1 reference turns out to be null.but when i inspect this.root it is referring to the correct root node..
Thanks!
Alright here is dry run for your code,
Inserting 10.
When you insert first element, this API insert creates a new root for you as per your code and sets it value to 10,
now second insertion makes it interesting, watch what happenes
StackTrace
insertData(15);
insert(node,root) // here root is your actuall root, originally initialized when u inserted first
// it goes to last else if inside insert api
root1.setRightChild(insert(node,root1.getRightChild())); // see now, this apis actually calls insert again, coz new node value was greater then root value
// this is how next stack trace will look like, as root right child was null
insert(node,null); // observer second argument is null again
now as per your Insert code will end up creating root again(root1 argument is null, first condition is executed), discarding previously defined root. this is what is causing your issue you are overriding your root again and again.
After inserting first node i.e root, left and right node will be null. Next time while inserting left or right child node you are not checking that condition.
private Node insert(Comparable<Node> node,Node root1)
{
if(root1==null)
{//insert as first element ie root
this.root=new Node(((Node)node).getData(),null,null);
}
else if(node.compareTo(root1) <0)
{
if(root1.getLeftChild()==null)
root1.setLeftChild(node);
else
root1.setLeftChild(insert(node,root1.getLeftChild()));
}
else if(node.compareTo(root1) >0)
{
if(root1.getRightChild()==null)
root1.setRightChild(node);
else
root1.setRightChild(insert(node,root1.getRightChild()));
}
return root1;
}

java program printing weird hexadecimal output

Ok i am trying to write a program for binary search tree. Everything looks good except my program keeps printing this instead of just my inorder traversal of integers.I tried to just just println in the main method and got the same thing?
This is my code:
public class bst {
Node root;
public Node getRoot(){
return root;
}
public bst(){
root=null;
}
//method addNode
public void insert(int key){
Node newNode= new Node(key);//initialize Node
if(root==null){
root=newNode;
}else{
Node focusNode=root;
Node insNode=root;
while(insNode!=null){
focusNode=insNode;
if(key<focusNode.getKey()){
insNode=insNode.getLeft();
}
else{
insNode=insNode.getRight();
}
}
if(key<focusNode.getKey()){
focusNode.setLeft(newNode);
}
else{
focusNode.setRight(newNode);
}
}
}
public void inOrder(Node focusNode){
if (focusNode !=null){
inOrder(focusNode.leftChild);
System.out.println(focusNode);
inOrder(focusNode.rightChild);
}
}
//Node class
class Node{
int key;
Node leftChild;
Node rightChild;
//Node constructor
Node(int key){
this.key=key;
leftChild=null;
rightChild=null;
}
public void setLeft(Node left){
this.leftChild=left;
}
public void setRight(Node right){
this.rightChild=right;
}
public Node getLeft(){return leftChild;}
public Node getRight(){return rightChild;}
public void setKey(int k){this.key=k;}
public int getKey(){return key;}
public void print(){
System.out.println(getKey());
}
}
public static void main(String[] args){
bst theTree= new bst();
theTree.insert(30);
theTree.insert(60);
theTree.insert(50);
theTree.insert(70);
theTree.inOrder(theTree.getRoot());
}
}
In the inOrder method, you do:
System.out.println(focusNode);
You are printing focusNode directly, so unless your Node class overrides the default toString method you will just see a hash code of your object (see this question for details if you are interested). You probably wanted something like
System.out.println(focusNode.getKey());
or simply using the print method you wrote instead.
It looks like you are trying to print the actual Node, which will just be the memory address that of that node. If you want to print the the integers, you should print the key to the node.
print(node.getKey());

Categories