Traversing through a generic binary tree - java

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

Related

Adding child to Tree using LinkedLists to store the value of Nodes

Ok so i want to implement a tree, of which the values of the children of each node are stored in a LinkedList. I have the following Code so far:
class Tree {
class Node {
int value;
LinkedList<Node> children = null;
Node(int value) {
this.value = value;
}
}
public Node root = null;
public void setRoot(Node root) {
root = this.root;
}
public Node getRoot() {
return root;
}
public void addChild(Node parent, Node child) {
}
}
Where I struggle is finding a way to add a child to this structure. I have looked for sites using a similar way to store the data of each node in LinkedLists but I couldn't find anything.
Here you go:
static class Tree {
static class Node {
int value;
LinkedList<Node> children;
Node(int value) {
this.value = value;
this.children = new LinkedList<>();
}
// Override equals to detect node equality based on the value
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Node node = (Node) o;
return value == node.value;
}
#Override
public int hashCode() {
return value;
}
#Override
public String toString() {
return value + "";
}
}
public Node root = null;
// Assign the root like this not like yours which was not correct
public void setRoot(Node root) {
this.root = root;
}
public Node getRoot() {
return root;
}
public void addChild(Node parent, Node child) {
// Check if the root is null and parent not null then add child to the root
if (root == null && parent != null) {
root = parent;
root.children.add(child);
return;
}
// if the parent equals root then add to the root's child
if (parent.equals(root)) {
root.children.add(child);
return;
}
// add recusively
addRecur(root, parent, child);
}
private void addRecur(Node parent, Node p, Node child) {
// base condition to the recursion
if (parent == null) {
return;
}
// if the parent equals to p then add to child
if (parent.equals(p)) {
parent.children.add(child);
return;
}
// loop over every child and check if equals p if not do recursion
for (Node node : parent.children) {
if (node.equals(p)) {
node.children.add(child);
return;
}
addRecur(node, p, child);
}
}
// print the tree
public void print() {
ArrayDeque<Node> queue = new ArrayDeque<>();
queue.add(root);
while (!queue.isEmpty()) {
Node current = queue.poll();
if (!current.children.isEmpty())
System.out.print("Parent: " + current + ", child: ");
for (Node node : current.children) {
if (!queue.contains(node)) {
System.out.print(node + " ");
queue.add(node);
}
}
if (!current.children.isEmpty())
System.out.println();
}
}
}
, Calls from main function
static public void main(String[] args) {
Tree tree = new Tree();
Tree.Node root = new Tree.Node(1);
tree.addChild(root, new Tree.Node(2));
tree.addChild(root, new Tree.Node(3));
tree.addChild(root, new Tree.Node(4));
tree.addChild(root, new Tree.Node(5));
tree.addChild(new Tree.Node(5), new Tree.Node(6));
tree.addChild(new Tree.Node(5), new Tree.Node(7));
tree.addChild(new Tree.Node(6), new Tree.Node(8));
tree.addChild(new Tree.Node(6), new Tree.Node(9));
tree.addChild(new Tree.Node(6), new Tree.Node(15));
tree.addChild(new Tree.Node(9), new Tree.Node(11));
tree.addChild(new Tree.Node(9), new Tree.Node(10));
tree.addChild(new Tree.Node(9), new Tree.Node(12));
tree.print();
}
, output
Parent: 1, child: 2 3 4 5
Parent: 5, child: 6 7
Parent: 6, child: 8 9 15
Parent: 9, child: 11 10 12
I think this code should work:
class Node {
int value;
LinkedList<Node> children = null;
Node(int value) {
this.value = value;
this.children = new LinkedList<Node>();
}
public void addChild(Node child) {
this.children.add(child);
}
}
and the function will look like this:
public void addChild(Node parent, Node child) {
parent.addChild(child);
}

Binary Tree in Java - why do i have an "empty" node (with a blank String) in my Tree?

Basically, my problem with my code is that somewhere in its implementation it creates a blank node which is then inserted into my binary tree. This node exists, as my sizeOfTree method counts it as such.
The code works just fine, the only problem is the node.
OK, so here I have defined the TreeNode based on which the Binary Tree is constructed:
package hr.fer.oop.lab1.prob6;
public class TreeNode {
TreeNode left=null;
TreeNode right=null;
String data;
public TreeNode(String data) {
this.data=data;
}
}
And here is the rest of it:
package hr.fer.oop.lab1.prob6;
import hr.fer.oop.lab1.prob6.TreeNode;
public class BinaryTree {
TreeNode root;
public BinaryTree() {
TreeNode node = new TreeNode("");
root=node;
}
public void insert (String data) {
if (this.root==null) {
this.root=new TreeNode(data);
return;
}
else {
TreeNode node = this.root;
TreeNode parent = new TreeNode("");
while(node!=null) {
parent = node;
if (node.data.compareTo(data)<=0) {
node=node.left;
}
else{
node=node.right;
}
}
if (parent.data.compareTo(data)<=0) {
parent.left=new TreeNode(data);
}
else {
parent.right=new TreeNode(data);
}
}
return;
}
private boolean subTreeContainsData(TreeNode node, String data) {
if ((node.data).compareTo(data)<1E-15) return true;
TreeNode temp=new TreeNode("");
temp=node;
if((temp.left.data).equals("")&&(temp.right.data).equals("")) return false;
return (subTreeContainsData(temp.left, data)||subTreeContainsData(temp.right, data));
}
private boolean containsData(String data) {
return subTreeContainsData(root, data);
}
private int sizeOfSubTree(TreeNode node) {
if (node==null) return 0;
return 1 + sizeOfSubTree(node.left) + sizeOfSubTree(node.right);
}
public int sizeOfTree() {
return sizeOfSubTree(root);
}
private void writeSubTree(TreeNode node) {
if (node!=null) {
writeSubTree(node.left);
System.out.println(node.data);
writeSubTree(node.right);
}
return;
}
public void writeTree() {
writeSubTree(root);
}
private void reverseSubTreeOrder(TreeNode node) {
if (node==null) return;
TreeNode helpNode;
helpNode=node.left;
node.left=node.right;
node.right=helpNode;
reverseSubTreeOrder(node.left);
reverseSubTreeOrder(node.right);
}
public void reverseTreeOrder() {
reverseSubTreeOrder(root);
}
public static void main (String[] args) {
BinaryTree tree = new BinaryTree();
tree.insert("Jasna");
tree.insert("Ana");
tree.insert("Ivana");
tree.insert("Anamarija");
tree.insert("Vesna");
tree.insert("Kristina");
System.out.println("Writing tree inorder:");
tree.writeTree();
tree.reverseTreeOrder();
System.out.println("Writing reversed tree inorder:");
tree.writeTree();
int size=tree.sizeOfTree();
System.out.println("Number of nodes in tree is "+size+".");
boolean found = tree.containsData("Ivana");
System.out.println("Searched element is found: "+found);
}
}
Much appreciate any help provided.
You create an empty TreeNode in your constructor and make it the root of the tree:
public BinaryTree() {
TreeNode node = new TreeNode("");
root=node;
}
Later, in your insert method, your if (this.root==null) condition is always false, so you don't assign the first inserted node to the root.
Just remove it:
public BinaryTree() {
}

Need guidance on creating Node class (java)?

I need to implement a Node class, where the basic methods are: getItem(), getNext(), setItem() and setNext(). I want the nodes to be able to store at least the default integer range in Java as the “item”; the “next” should be a reference or pointer to the next Node in a linked list, or the special Node NIL if this is the last node in the list.I also want to implement a two-argument constructor which initializes instances with the given item (first argument) and next node (second argument) , I've kind of hit a brick wall and need some guidance about implementing this , any ideas ?
I have this so far:
class Node {
public Node(Object o, Node n) {
}
public static final Node NIL = new Node(Node.NIL, Node.NIL);
public Object getItem() {
return null;
}
public Node getNext() {
return null;
}
public void setItem(Object o) {
}
public void setNext(Node n) {
}
}
While implementing the custom LinkedList/Tree, we need Node. Here is demo of creating Node and LinkedList. I have not put in all the logic. Just basic skeleton is here and you can then add more on yourself.
I can give you a quick hint on how to do that:
Class Node{
//these are private class attributes, you need getter and setter to alter them.
private int item;
private Node nextNode;
//this is a constructor with a parameter
public Node(int item)
{
this.item = item;
this.nextNode = null;
}
// a setter for your item
public void setItem(int newItem)
{
this.item = newItem;
}
// this is a getter for your item
public int getItem()
{
return this.item;
}
}
You can create a Node object by calling:
Node newNode = Node(2);
This is not a complete solution for your problem, the two parameter constructor and the last node link are missing, but this should lead you in the correct direction.
Below is a simple example of the Node implementation, (i renamed Item to Value for readability purpose). It has to be implemented somehow like this, because methods signatures seems to be imposed to you. But keep in mind that this is definely not the best way to implement a LinkedList.
public class Node {
public static final Node NIL = null;
private Integer value;
private Integer next;
public Node(Integer value, Node next) {
this.value = value;
this.next = next;
}
public Integer getValue() {
return this.value;
}
public Node getNext() {
return this.next;
}
public void setValue(Integer value) {
this.value = value;
}
public void setNext(Node next) {
this.next = next;
}
public boolean isLastNode() {
return this.next == Node.NIL || Node;
}
}
public class App {
public static void main(String[] args) {
Node lastNode = new Node(92, Node.NIL);
Node secondNode = new Node(64, lastNode);
Node firstNode = new Node(42, secondNode);
Node iterator = firstNode;
do () {
System.out.println("node value : " + iterator.getValue());
iterator = iterator.getNext();
} while (iterator == null || !iterator.isLastNode());
}
}
The node class that will be implemented changes according to the linked list you want to implement. If the linked list you are going to implement is circular, then you could just do the following:
public class Node {
int data;
Node next = null;
public Node(int data){
this.data = data;
}
}
Then how are you going to implement the next node?
You are going to do it in the add method of the circularLinkedList class. You can do it as follows:
import java.util.*;
public class CircularLinkedList {
public CircularLinkedList() {}
public Node head = null;
public Node tail = null;
public void add(int data) {
Node newNode = new Node(data);
if(head == null) {
head = newNode;
}
else {
tail.next = newNode;
}
tail = newNode;
tail.next = head;
}
public void displayList() {
System.out.println("Nodes of the circular linked list: ");
Node current = head;
if(head == null) {
System.out.println("Empty list...");
}
else {
do {
System.out.print(" " + current.data);
current = current.next;
}while(current != head);
System.out.println();
}
}
}

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.

Class cast exception while adding a second tree node to PriorityQueue

I am trying to print a binary tree by BFS.
my implementation is with a PriorityQueue.
in the beginning i insert root into PriorityQueue.
then in loop, i pull a node from PriorityQueue, print it, and insert his childs(if thay are not null) into PriorityQueue.
why when inserting the second node, i get this exception:
Exception in thread "main" java.lang.ClassCastException: Node cannot be cast to java.lang.Comparable
this is my code:
class main:
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Tree tree = new Tree();
}
}
class Node:
public class Node {
public Node(){}
public Node(int num)
{
value = num;
}
private int value;
private Node left;
private Node right;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
}
class tree:
public class Tree {
private Node root;
public Tree()
{
root = new Node(5);
Node node2 = new Node(2);
Node node10 = new Node(10);
Node node8 = new Node(8);
Node node6 = new Node(6);
Node node15 = new Node(15);
root.setRight(node10);
root.setLeft(node2);
node10.setRight(node15);
node10.setLeft(node8);
node8.setLeft(node6);
printToWidth(root);
}
public void printToWidth(Node node)
{
PriorityQueue<Node> queue = new PriorityQueue<Node>();
queue.add(node);
while( !(queue.isEmpty()))
{
Node n = queue.poll();
System.out.println(n.getValue());
if (n.getLeft() != null)
queue.add(n.getLeft());
if (n.getRight() != null)
queue.add(n.getRight());
}
System.out.println("end printToWidth");
}
}
You've got two options:
Make Node implement Comparable<Node>, so that the elements can be inserted according to their natural ordering. This is likely the easier of the two.
public int compareTo(Node other) {
return value - other.getValue();
}
Use a custom Comparator<Node> and supply a compare method there, with an initial capacity.
PriorityQueue<Node> queue = new PriorityQueue<Node>(10, new Comparator<Node>() {
public int compare(Node left, Node right) {
return left.getValue() - other.getValue();
}
});
The exception is telling you, make Node implement Comparable<Node>.
You can insert the first node because it has nothing to compare to, so the comparison is not needed.

Categories