Binary Tree method instance - java

When I was coding a generic "BinaryTree", I needed a method to sum the values of all left subtrees in a tree. This method should return an integer value in a recursive way. However, when I tried to add the root value to the summation, I couldn't cast the "T" value to "int" because the "T" value is incompatible. I created a child class that extends from "BinaryTree" using integer type. In this case, I needed to create the method in my parent class because the recursive call needs to use the method in the parent class and it is a bit annoying me. I think that there is another way to avoid this behavior. Is there a way to avoid creating the method in my parent class?
Binary Tree Class:
public class BinaryTree<T> {
protected T root= null;
protected BinaryTree<T> left= null, right= null;
//All binary tree here
Integer sumLeft() {
return 0;
}
Binary Tree Integer
public class BinaryTreeInteger extends BinaryTree<Integer> {
//All code here
Integer sumLeft() {
int suma = 0;
if (isLeaf()) {
return getRaiz();
}
if (left != null) {
if (!left.EsHoja()) {
suma += left.getRaiz() + left.sumLeft();
} else {
suma += left.sumLeft();
}
}
if (right != null && !right.isLeaf()) {
suma += right.sumLeft();
}
return suma;
}
}
}

Related

Adding height of binary tree to insert method

I am creating a program that inserts a character (number/letter) into a binary tree. So far, I'm able to produce an output but it's not what I expected. These are the problems I'm encountering:
The insert method is not able to print the correct height of the tree. I am not sure where I should insert my height++; statement to get the correct output.
The insert method is only able to add nodes to the right.
Expected Output: ht=3 [K=3 L=[K=1 R=[K=2]] R=[K=5 L=[K=4]]]
My Output: ht=4 [K=3 R=[K=1 R=[K=2 R=[K=5 R=[K=4]]]]
(all nodes are only added to the right 'R')
Here are my classes for reference:
Main Class
BST<Character> bst = new BST<>();
bst.insert('3');
bst.insert('1');
bst.insert('2');
bst.insert('5');
bst.insert('4');
System.out.println("ht=" + bst.height + " " + bst.toString());
BST Class - where the insert method is declared
public class BST<T> extends BT<T> {
// insert() method
public void insert(char k)
{
if (root == null) {
root = new BTNode(k);
return;
}
BTNode<T> n = root;
BTNode<T> p = null; // parent
while (n != null) {
p = n;
if (k < n.value) {
n = n.left;
} else {
n = n.right;
}
}
if (k < p.value) {
p.left = new BTNode(k);
} else {
p.right = new BTNode(k);
height++; // adds 1 to height when a new level is made
}
}
}
BTNode Class
public class BTNode<T> {
T info;
int value, level;
BTNode<T> left, right;
public BTNode(T el) {
this(el, null, null);
}
public BTNode(T el, BTNode<T> l, BTNode<T> r) {
info = el;
left = l;
right = r;
}
}
BT Class - where the toString method is declared
public class BT<T> {
BTNode<T> root = null;
int height = 0;
public BT() {
BTNode<T> node = new BTNode("");
}
// other methods
// toString()
public String toString() {
return toString(root);
}
public String toString(BTNode<T> n) {
String s = "";
if (n == null) {
return "";
}
if (n != null) {
s = "[K=" + n.info;
if (n.left != null) {
s = s + " L=" + toString(n.left) + "]";
}
if (n.right != null) {
s = s + " R=" + toString(n.right) + "]";
}
}
return s;
}
}
Hope you can help me out, thanks!
You have quite a few issues in your code. I'll list a few immediate items but you really will need to learn to use an interactive debugger and unit testing to resolve the sorts of issues you are seeing.
You refer to the value field in BTNode in your comparison but it is never set. You should really be referring to info (which is the actual data in the node).
But given info is a generic type you can't use standard comparison operators. Instead you'll need to define it as <T extends Comparable<T>> and then use n.info.compareTo(k) > 0.
The key passed into insert should also be of type T
Which means the other classes also need to ensure T extends Comparable.
Height is only incremented when nodes are added to the right which makes no sense.
Height needs to be increased only when a node is inserted further from the root than the current maximum. Something like the following:
int depth = 0;
while (n != null) {
depth++;
p = n;
...
}
depth++;
if (depth > height)
height = depth;
You should get used to making your fields private and accessing them through getters. In your case a compareValue method would likely make sense.

How to use a Method from a nested class inside the Body of a Method from the first layer class

I am Studying Systems-Engineering for just 2 Month so please go easy on me. I am working on a Project with lists, stacks and Binary Trees. The Code I am having trouble with is the one inside of the Binary Tree.
public class BinaryIntTree {
public static class Node {
int value;
The left child.
Node leftChild;
public int getNodeCount(Node node) {
if(node == null) {return 0;}
int counter = 0;
if(node.leftChild == null && node.rightChild == null) {
return 1;
} else {
counter += 1;
if (node.leftChild != null) {
counter += getNodeCount(node.leftChild);
}
if (node.rightChild != null) {
counter += getNodeCount(node.rightChild);
}
}
return counter;
}
public Node(int value) {
this.value = value;
}
public int getNodeCount() {
return root.getNodeCount(root);
}
the second getNodeCount() is in the Main class and I want, that if I use getNodeCount(), that I can't change the Object(root), which is used as the starting point. So I thought id just implement it in the nested Node class and let it be called in the Method from the Main class.
But it throws out a NullPointerException, which should be solved with if(node == null) {return 0;} but it does not.
Thank you for your help in advance, also please no comment on the Method per se, since I want to solve the recursive method myself.
getNodeCount takes a Node as an argument, and doesn't use the Node instance it's called upon (i.e., the this), meaning it should probably be static. Once you make it static, you can call it without an instance, and thus avoid the NullPointerException you're running into:
public int getNodeCount() {
return Node.getNodeCount(root);
}

Casting with Comparable

I'm trying to find the minimum value of a node within a tree, and in order to detect whether something has smaller value, I'm using the compareTo() function as seen below:
#SuppressWarnings("unchecked")
public static Object min(TreeNode t)
{
if(t == null) {
return null;
}
Comparable<TreeNode> min = (Comparable<TreeNode>) t;
if(t.getLeft() != null) {
Comparable<TreeNode> leftMin = (Comparable<TreeNode>) min(t.getLeft());
if( ((Comparable<TreeNode>)leftMin).compareTo( (Comparable<TreeNode>)min) < 0) {
min = leftMin;
}
}
if(t.getRight() != null) {
Comparable<TreeNode> rightMin = (Comparable<TreeNode>) min(t.getRight());
if( ((Comparable<TreeNode>)rightMin).compareTo( (Comparable<TreeNode>)min) < 0) {
min = rightMin;
}
}
return min;
}
However, I'm receiving the following error:
error: incompatible types: Comparable<TreeNode> cannot be converted to TreeNode
at the if statement.
I was told that the Object must be cast to Comparable in order to call compareTo()
And I have tried looking at this similiar question, but I don't have access to change the TreeNode Class
TreeNode Class:
public class TreeNode
{
private Object value;
private TreeNode left, right;
public TreeNode(Object initValue)
{
value = initValue;
left = null;
right = null;
}
/*methods*/
}
And I have also tried: if(leftMin.compareTo(min) < 0) however that yields the same error.
Do you know how to properly cast and convert the following classes?
As suggested by others, you can use the comparable interface, which will require you to implement the compareTo method.
The compare to implementation details can be found in the java se docs:
Compares this object with the specified object for order. Returns a
negative integer, zero, or a positive integer as this object is less
than, equal to, or greater than the specified object.
So we can change your class to something like what is shown below (Note: I recommend converting value to an int or any other primitive type):
class TreeNode implements Comparable<TreeNode> {
// recommend to convert value to int or any other primitive type
private Object value;
private TreeNode left, right;
public TreeNode(Object initValue) {
value = initValue;
left = null;
right = null;
}
// if value is int, just use ==, < and >
// i.e. this.value == o.value, this.value < o.value and so on ...
#Override
public int compareTo(TreeNode o) {
if (this.value.equals(o.value)) return 0;
else if (this.value.hashCode() < o.value.hashCode()) return -1;
else return 1;
}
/*methods*/
}
Then you don't really need to do the casting in the min method. (Note: The implementation below is not actually correct - won't give you the min. It's just shown as to how the implementation would change after implementing the comparable interface).
// This method is not actually correct (i.e. won't actually find the min),
// but showing how it would change after using the comparable interface
// on the tree node class.
public TreeNode min(TreeNode t) {
if(t == null) {
return null;
}
TreeNode min = t;
if(t.getLeft() != null) {
TreeNode leftMin = min.getLeft();
if(leftMin.compareTo(min) < 0) {
min = leftMin;
}
}
if(t.getRight() != null) {
TreeNode rightMin = min.getRight();
if( rightMin.compareTo(min) < 0) {
min = rightMin;
}
}
return min;
}
The class TreeNode must implement the Comparable interface:
public class TreeNode implements Comparable<TreeNode> {
...
#Override
public int compareTo(TreeNode other) {
... // maybe compare 'initValue' here
}
}
also not sure if it is so good to cast TreeNode to Comparable, I would prefer to work
without casting at all (e.g. public static TreeNode min(TreeNode t))
Edit: probably it was meant to cast initValue to Comparable so it can be compared - not very (type-) safe having it declared as Object in that case.
Edit after question changed. Since TreeNode cannot be changed, I think you must clearly split nodes and values, probably something like below (must be completed):
public static TreeNode min(TreeNode node) {
...
TreeNode minNode = node;
Comparable<?> minValue = (Comparable<?>) minNode.getValue(); // guessed method name
if (node.getLeft() != null) {
TreeNode leftMin = min(t.getLeft());
Comparable<?> leftValue = (Comparable<?>) leftMin.getValue();
if (leftValue.compareTo(minValue) < 0) {
minNode = leftNode;
minValue = leftValue;
}
...
This requires that instances in Value implement Comparable.

How do I do a pre-order traversal in Java?

I'm attempting to write a pre-order traversal algorithm on a binary tree using the recursive method. Here's what I have:
void traverse(BT t) {
if (t == null){
return;
}
System.out.print(t);
traverse(t.left);
traverse(t.right);
}
That doesn't compile for some reason. I think the problem is with the rest of my code. Here's the entire code:
class ZOrep extends TreeAndRepresentation {
private int k;
ZOrep left;
ZOrep right;
ZOrep( int m, int[] b ) { // given sequence build tree
super( m, b );
N = (M-1)/2;
k = -1;
t = build();
}
ZOrep( int n, BT t ) { // given tree build sequence
super(n, t);
t = build();
traverse( t );
}
BT build() {
return(a[++k] == 0 ? null : new BT( build(), build() ));
}
void traverse(BT t) {
if (t == null){
return;
}
System.out.print(t);
traverse(t.left);
traverse(t.right);
}
}
I feel like I'm missing something when I'm building the tree (with my ZOrep method). Also here's the BT class:
class BT {
BT L; BT R;
BT( BT l, BT r ) { L = l; R = r; }
}
Currently my compiler says it can't find the symbol for t.left and t.right.
When the compiler says it can't find the symbol, it means the field you're trying to reference doesn't exist.
Looking at your class BT, this is correct; BT doesn't have left or right, it has L and R. Thus, replacing
traverse(t.left);
traverse(t.right);
with
traverse(t.L);
traverse(t.R);
Will fix this issue.
Currently my compiler says it can't find the symbol for t.left and t.right.
This is because t is a BT and it doesn't have a left and a right.
I suggest you decide what you want to call your tree node class. Is it ZOrep or BT and only use one of these or you will create confusion.
System.out.print(t);
If you want to print out a BT, you will need to add a toString() method to it as the default won't tell you anything useful.
What are you passing into your transverse function? If it's a BT object, then you can't use left and right, you must use L and R. Left and right are parts of your object that extends from BT, but it looks like you're passing in a BT.
// Java
static String tree = "";
private static void preOrder(HuffTree currentObject) {
if (currentObject == null) {
return;
}
if (currentObject.filling == null) tree += 1;
else tree += 0;
preOrder(currentObject.child0);
preOrder(currentObject.child1);
}
}
// class code here
import java.util.Objects;
/**
Huffman tree as class
*/
class HuffTree implements Comparable {
// element filling
Byte filling;
// element repeats
int repeats;
// zero child
HuffTree child0;
// child 1
HuffTree child1;
/**
* constructor for tree fathers and leaves
*/
public HuffTree(Byte filling, int repeats, HuffTree child0, HuffTree child1) {
// father filling
this.filling = filling;
// father repeats
this.repeats = repeats;
// zero child
this.child0 = child0;
// child 1
this.child1 = child1;
}
/**
* finding difference between our tree's items
*/
#Override
public int compareTo(HuffTree currentByte) {
return currentByte.repeats - repeats;
}
/**
* take byte code as a string by recursive three search in depth
*/
public String getCodeForByte(Byte currentByte, String wayToFather) {
// there is 4 cases:
if (!Objects.equals(filling, currentByte)) {
// case 1 - zero child found
if (child0 != null) {
// recursive code add for zero child
String currentWay = child0.getCodeForByte(currentByte, wayToFather + "0");
// return temporary string
if (currentWay != null) return currentWay;
}
// case 2 - child 1 found. recursive code add for child 1. return temporary string
if (child1 != null) return child1.getCodeForByte(currentByte, wayToFather + "1");
}
// case 3 - correct leaf found. return correct code
if (Objects.equals(filling, currentByte)) return wayToFather;
// case 4 - wrong leaf found. return null
return null;
}
}

Why does this method cause an Infinite Recursive call?

I'm struggling to understand why this class is not functioning. It was part of an assignment for a course on Data Structures(EDIT: The deadline for the assignment has passed, I just want to figure it out...). The node is part of an AVL tree built upon a BST and the way I chose to implement it is by creating methods within my Node class to find the Balance factor and height.
The class is structured as follows:
public class Node<T extends Comparable<? super T>> {
public T data;
public Node left;
public Node right;
public Node(T IN) {
data = IN;
}
public Node(T IN, Node L, Node R) {
this(IN);
left = L;
right = R;
}
#Override
public String toString() {
return data.toString();
}
#Override
public Node clone() {
return new Node(this.data) ;
}
public int getHeight() {
return getHeight(this) ;
}
public int getBF() {
//Calculate BF
int balanceFactor = 0;
if (right != null && left != null)
balanceFactor = getHeight(right) - getHeight(left);
else if (left != null) {
balanceFactor = 0 - getHeight(left) ;
}
else if (right != null) {
balanceFactor = getHeight(right) ;
}
else
balanceFactor = 0 ;
return balanceFactor ;
}
private int getHeight(Node p) {
if (p.left == null && p.right == null ) {
return 0 ;
}
else if (p.left != null && p.right != null) {
return 1 + max(p.left.getHeight(), p.right.getHeight());
}
else if (p.left != null) {
return 1 + p.left.getHeight() ;
}
else if (p.right != null) {
return 1 + p.right.getHeight() ;
}
else {
return 0;
}
}
private int max(int x, int y) {
if (x >= y) {
return x;
} else {
return y;
}
}
}
and the function calling the method is:
#Override
public boolean insert(T el) {
boolean test = super.insert(el) ;
if (test) {
return checkBalance(root) ;
}
else
return false ;
}
and the exception I recieve is a repetition of:
Exception in thread "main" java.lang.StackOverflowError
at Node.getHeight(Node.java:54)
at Node.getHeight(Node.java:33)
at Node.getHeight(Node.java:58)
I would suggest that either your tree is deformed or really big. There seems to be no problems with the code.
If your tree is deformed in such a way that you have a Node inserted twice in the same tree then this code will break.
Added - You are eating a little more stack than you need - replacing p.left.getHeight() with getHeight(p.left) etc. would avoid one stack push per recursion. If your issue is merely big tree then this might scrape you through but this would only postpone the problem.
From looking at both getHeight methods, it seems like you don't have a tree but a cyclic graph. You should start testing with a tree consisting of only the root and then add nodes until you observe the infinite recursion. You probably have an error in the function that rebalances the tree.
EDIT: And you should make the attributes (at least left and right) private.

Categories

Resources