Iterate through Binary search tree java - java

Can some one show me the way to loop a binary tree in order to traverse all nodes.
I will add students by insert method.
I just want to print all the students objects.
This is my BST :
public class BinarySearchTree<Students extends Comparable<? super Student>> {
public static BinaryNode root;
public BinarySearchTree() {
this.root = null;
}
public void insert(Student student) {
root = insert(student, root);
}
protected BinaryNode<Student> insert(Student student, BinaryNode<Student> t) {
if (t == null) {
t = new BinaryNode<Student>(student);
} else if (student.compareTo(t.element) < 0) {
t.left = insert(student, t.left);
} else if (student.compareTo(t.element) > 0) {
t.right = insert(student, t.right);
} else {
// throw new DuplicateItemException(student.toString());
}
return t;
}
}
Node Class :
class BinaryNode<Student> {
// Constructor
BinaryNode(Student theElement) {
element = theElement;
left = right = null;
}
// Data; accessible by other package routines
Student element; // The data in the node
BinaryNode<Student> left; // Left child
BinaryNode<Student> right; // Right child
}

Add this method to the BinarySearchTree class:
public void inorder(BinaryNode node) {
if (node == null) {
return;
}
inorder(node.left);
System.out.print(...); //whatever you want to do with the node
inorder(node.right);
}
In a similar way you can do preorder and postorder traversals.

There are 3 ways to traverse Binary Search Trees.
Pre-order
public void preOrder(BinaryNode node) {
if (node == null) {
return;
}
doSomethig(node.element); // process node
preOrder(node.left);
preOrder(node.right);
}
In-order in this case nodes are traversed in order
public void inOrder(BinaryNode node) {
if (node == null) {
return;
}
inOrder(node.left);
doSomethig(node.element); // process node
inOrder(node.right);
}
Post-order
public void postOrder(BinaryNode node) {
if (node == null) {
return;
}
postOrder(node.left);
postOrder(node.right);
doSomethig(node.element); // process node
}
You have to choose one of these and run for example:
preOrder(root); // where root is a handle to your BST

public class BinarySearchTree<Students extends Comparable<? super Student>> {
public static BinaryNode root;
public BinarySearchTree() {
this.root = null;
}
...
public void print() {
print(root);
}
public void print(BinaryNode<Student> node) {
if (node == null) {
return;
}
print(node.left);
doSomething(node.getStudent());
print(node.right);
}
}

Related

Traversing through a generic binary tree

An abstract binary tree is to be created using a generic class. Each node has a string value as well as an initialCalculatedValue value. No changes should be made to the main class and a static inner class is to be included in the generic class. I'd like some advice on my code, as the main class is giving me error on accessing 'timesVisited' and 'values'. My code can't seem to access those variables.
Main class code:
public class Main{
public static void main(String[] args) {
WalkableTree<String, Integer> ast = new WalkableTree<>(0);
WalkableTree.Node<String, Integer> plus = ast.setRoot("+");
plus.setRightChild("20");
WalkableTree.Node<String, Integer> multiply = plus.setLeftChild("*");
multiply.setLeftChild("10");
WalkableTree.Node<String, Integer> bracketedPlus = multiply.setRightChild("+");
bracketedPlus.setLeftChild("3");
bracketedPlus.setRightChild("4");
// write visitor to display pre-order
System.out.println("Pre-order traversal:");
ast.walk(current -> {
if(current.timesVisited == 2)
System.out.print(current.value + " ");
});
System.out.println();
// write visitor to display in-order
System.out.println("In-order traversal:");
ast.walk(current -> {
if(current.timesVisited == 3)
System.out.print(current.value + " ");
});
System.out.println();
// write visitor to display post-order
System.out.println("Post-order traversal:");
ast.walk(current -> {
if(current.timesVisited == 4)
System.out.print(current.value + " ");
});
System.out.println();
}
}
Functional interface:
#FunctionalInterface
public interface Visitor<N> {
public void visit(N node);
}
Generic class:
public class WalkableTree <T, R> {
private T root = null;
private R initialCalculatedValue;
public static Node current;
public WalkableTree(R initialCalculatedValue) {
this.initialCalculatedValue = initialCalculatedValue;
}
public Node getRoot() {
return (Node) root;
}
public Node setRoot(T value) {
current = new Node(null,null,null,value,null,0);
return current;
}
public R getInitialCalculatedValue() {
return initialCalculatedValue;
}
public void setInitialCalculatedValue(R initialCalculatedValue) {
this.initialCalculatedValue = initialCalculatedValue;
}
protected void reset(Node node) {
node.timesVisited = 0;
node.calculatedValue = initialCalculatedValue;
reset((Node) node.leftChild);
reset((Node) node.rightChild);
}
public Node nextNode(Node node) {
node.timesVisited++;
if(node.timesVisited == 1)
return node;
if(node.timesVisited == 2)
return (Node) node.leftChild;
if(node.timesVisited == 3)
return (Node) node.rightChild;
if(node.timesVisited == 4)
return (Node) node.getParent();
return node;
}
public void walk(Visitor visitor) {
//Reset all the nodes in the tree
reset((Node) root);
//Set the current node to visit at the root of the tree
visitor.visit(root);
//Walking through the tree as long as the current node still exists
//If current node exists, let the visitor object visit the current node
//Current node is set to the next node using nextNode() method
while (this.current == current)
{
nextNode(current);
}
}
public static class Node<T, R> {
//Variables
Object leftChild;
Object rightChild;
Object parent;
T value;
R calculatedValue;
int timesVisited = 0;
public Node(Object leftChild, Object rightChild, Object parent, T value, R calculatedValue, int timesVisited) {
this.leftChild = leftChild;
this.rightChild = rightChild;
this.parent = parent;
this.value = value;
this.calculatedValue = calculatedValue;
this.timesVisited = timesVisited;
}
public Object getLeftChild() {
return leftChild;
}
public Node setLeftChild(T value) {
Node newLeft = new Node(null,null, current,value,0,0);
current = newLeft;
return current;
}
public Object getRightChild() {
return rightChild;
}
public Node setRightChild(T value) {
Node newRight = new Node(null,null, current,value,0,0);
current = newRight;
return current;
}
public Object getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public R getCalculatedValue() {
return calculatedValue;
}
public void setCalculatedValue(R calculatedValue) {
this.calculatedValue = calculatedValue;
}
public int getTimesVisited() {
return timesVisited;
}
public void setTimesVisited(int timesVisited) {
this.timesVisited = timesVisited;
}
}
}
Update the method in WalkableTree as below:
public void walk(Visitor<Node> visitor) {
//Reset all the nodes in the tree
reset((Node) root);
//Set the current node to visit at the root of the tree
visitor.visit((Node) root);
//Walking through the tree as long as the current node still exists
//If current node exists, let the visitor object visit the current node
//Current node is set to the next node using nextNode() method
while (this.current == current)
{
nextNode(current);
}
}

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.

Is my Binary Tree adding nodes properly?

I've just created a method to test the height of my binary tree implementation as follows:
public int height() {
return height(rootNode);
}
private int height(BinaryTreeNode node) {
if(node == null) return -1;
else return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild()));
}
But it returns a height of 6, and not 7 when i add the nodes 1-6.
Here is my Binary Tree code:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
public class BinaryTree<E extends Comparable<E>>
{
private class BinaryTreeNode
{
private E value;
private BinaryTreeNode leftChild, rightChild;
public BinaryTreeNode(E value) {
this(value, null, null);
}
public BinaryTreeNode(E value, BinaryTreeNode leftChild, BinaryTreeNode rightChild) {
this.value = value;
this.leftChild = leftChild;
this.rightChild = rightChild;
}
public E getValue() {
return value;
}
public BinaryTreeNode getLeftChild() {
return leftChild;
}
public BinaryTreeNode getRightChild() {
return rightChild;
}
public void setLeftChild(BinaryTreeNode newLeftChild) {
this.leftChild = newLeftChild;
}
public void setRightChild(BinaryTreeNode newRightChild) {
this.rightChild = newRightChild;
}
}
private BinaryTreeNode rootNode;
public BinaryTree() {
this.rootNode = null;
}
public void addNode(E value) {
if(rootNode == null)
rootNode = new BinaryTreeNode(value);
else
addNode(value, rootNode);
}
//TODO: Implement removeNode()
public void printLevelOrder() {
printLevelOrder(rootNode);
}
public int height() {
return height(rootNode);
}
public void inOrderTraversal() {
if(rootNode != null) inOrderTraversal(rootNode);
else System.out.println("The tree is empty!");
}
private void addNode(E value, BinaryTreeNode node) {
if(node.getValue().compareTo(value) > 0) {
if(node.getLeftChild() != null)
addNode(value, node.getLeftChild());
else
node.setLeftChild(new BinaryTreeNode(value));
} else {
if(node.getRightChild() != null)
addNode(value, node.getRightChild());
else
node.setRightChild(new BinaryTreeNode(value));
}
}
private void printLevelOrder(BinaryTreeNode node) {
Queue<BinaryTreeNode> currentLevel = new LinkedList<BinaryTreeNode>();
Queue<BinaryTreeNode> nextLevel = new LinkedList<BinaryTreeNode>();
currentLevel.add(node);
while (!currentLevel.isEmpty()) {
Iterator<BinaryTreeNode> iter = currentLevel.iterator();
while (iter.hasNext()) {
BinaryTreeNode currentNode = iter.next();
if (currentNode.leftChild != null) {
nextLevel.add(currentNode.leftChild);
}
if (currentNode.rightChild != null) {
nextLevel.add(currentNode.rightChild);
}
System.out.print(currentNode.value + " ");
}
System.out.println();
currentLevel = nextLevel;
nextLevel = new LinkedList<BinaryTreeNode>();
}
}
private int height(BinaryTreeNode node) {
if(node == null) return -1;
else return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild()));
}
private void inOrderTraversal(BinaryTreeNode node) {
if(node != null) {
inOrderTraversal(node.leftChild);
System.out.println(node.getValue() + " ");
inOrderTraversal(node.getRightChild());
}
}
public BinaryTreeNode getRoot() {
return rootNode;
}
}
I think the problem is adding my node into the tree, but I've taken a look at other examples but they all seem to be doing the same thing I am.. So i can't realise the problem!
Thanks!
private int height(BinaryTreeNode node) {
if(node == null) return 0;
else return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild()));
}
You were returning -1 on node==null when you should return 0.
The condition is true when we arrive to leaf so for example if we add 1-2 then we have height as 1+Max(leftof(1),rightof(1))=
1+Max(height(null),height(2))=
1+Max(0,1+Max(leftof(2),rightof(2)))=
1+Max(0,1+Max(height(null),height(null)))=
1+Max(0,1+Max(0,0))=
1+Max(0,1+0)=
1+1=2.
Try to replace height(null) with -1 in the previous example to see by yourself.
By the way your BinaryTree implementation is actually a binary search tree since you're putting less elements on the left and bigger elements on the right, If a search tree is your intention then Ok but if you want to implement a general binary tree then you should change the add function.

Binary Search Tree insertion - root remains null

I'm new to Java, I want to create a Binary Search Tree class with insertion and preorder traversal, but when I finish the insertion the root object remains null and the compiler throws NullPointerException during the preorder traversal.
My node class:
class Node {
int info;
Node left;
Node right;
public Node() {
info = 0;
left = null;
right = null;
}
Node(int x) {
info = x;
left = null;
right = null;
}
}
My Binary Search Tree class:
public class BinarySearchTree {
private Node root;
public BinarySearchTree() {
root = null;
}
private void insertPrivate(Node node, int x) {
if(node == null) {
node = new Node(x);
}
else {
if(x < node.info) {
insertPrivate(node.left, x);
}
else if (x > node.info) {
insertPrivate(node.right, x);
}
}
}
public void insert(int x) {
insertPrivate(root, x);
}
private void preorderPrivate(Node node) {
if(node != null) {
System.out.println(node.info);
preorderPrivate(node.left);
preorderPrivate(node.right);
}
}
public void preorder() {
preorderPrivate(root);
}
public static void main(String[] args) {
BinarySearchTree t = new BinarySearchTree();
t.insert(12);
t.insert(13);
t.preorder();
}
}
The issue is a misunderstanding of Java referencing as seen with this section of code.
private void insertPrivate(Node node, int x) {
if(node == null) {
node = new Node(x);
}
....
Java references are passed by value into function arguments.
Let me give you an example to clarify.
Node root = new Node(x);
// root == Node(x);
doSomething(root);
// Pass Node(x) into function;
void doSomething(Node node) {
// root == Node(x);
// node == Node(x);
node = new Node(y); // This updates node but not root
// root == Node(x);
// node == Node(y);
}
You are going to have to restructure your program. One way would be to have insertPrivate return a Node and assign that value to root. It is not the most efficient but it will work.
public void insert(int x) {
root = insertPrivate(root, x);
}
private Node insertPrivate(Node node, int x) {
if(node == null) {
node = new Node(x);
}
else {
if(x < node.info) {
node.left = insertPrivate(node.left, x);
}
else if (x > node.info) {
node.right = insertPrivate(node.right, x);
}
}
return node;
}
Change insert(int x) like this:
public void insert(int x) {
if (root == nul)
root = new Node(x);
else
insertPrivate(root, x);
}
Try :
Node left = new Node();
Node right = new Node();
You should somehow return the newly created node and assign it to the left or right node of the parent. Try this:
private Node insertPrivate(Node node, int x) {
if(node == null) {
node = new Node(x);
}
else {
if(x < node.info) {
node.left = insertPrivate(node.left, x);
}
else if (x > node.info) {
node.right = insertPrivate(node.right, x);
}
}
return node;
}
And your public insert function should be:
public void insert(int x) {
root = insertPrivate(root, x);
}
Also preorderPrivate needs a null-checking:
private void preorderPrivate(Node node) {
System.out.println(node.info);
if (node.left != null)
preorderPrivate(node.left);
if (node.right != null)
preorderPrivate(node.right);
}

Error adding Strings to a BST

I'm adding values from an ArrayList of Strings to a BST and I'm coming up with a null pointer error on my line "tree.add(s);" and after tracing my code I can't figure out why this is happening. Can someone please help:
public class BinaryTree {
public Node root;
public BinaryTree tree;
private static class Node {
Node left;
Node right;
String data;
Node(String s) {
left = null;
right = null;
data = s;
}
}
public BinaryTree plantTree(ArrayList<String> dict) {
Collections.shuffle(dict);
for (String s : dict) {
s.toUpperCase();
System.out.print(s);
tree.add(s);
}
System.out.print(tree);
System.out.println();
return tree;
}
/**
* Creates an empty binary tree
*/
public BinaryTree() {
root = null;
}
public boolean search(String data) {
return (search(root, data));
}
private boolean search(Node node, String data) {
if (node == null) {
return (false);
}
if (data == node.data) {
return (true);
} else if (data.compareTo(node.data) > 0) {
return (search(node.left, data));
} else {
return (search(node.right, data));
}
}
public void add(String data) {
root = add(root, data);
}
private Node add(Node node, String data) {
if (node == null) {
node = new Node(data);
} else {
if (data.compareTo(node.data) > 0) {
node.left = add(node.left, data);
} else {
node.right = add(node.right, data);
}
}
return (node);
}
}
You have to set the tree variable to something before using it. For example:
public BinaryTree plantTree(ArrayList<String> dict) {
tree = new BinaryTree(); // important!
Collections.shuffle(dict);
for (String s : dict) {
s.toUpperCase();
System.out.print(s);
tree.add(s);
}
System.out.print(tree);
System.out.println();
return tree;
}
Maybe tree should be a local variable of the method rather than an instance variable?

Categories