Casting with Comparable - java

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.

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.

Binary Tree method instance

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

HashMap.containsKey(key) failing to find key, with custom class used as key type

TL;DR: I made a hashmap object with my own "Pair" class objects to be used as Keys. When I use hashmap.containsKey(Pair), it fails to find the key.
I have a class called Pair, code shown below. It's supposed to be a container for two objects. The first object can be of any type, whereas the second object must be an integer. This isn't great design but I coded it this way so I could reuse the class for other purposes within my program.
import java.util.ArrayList;
public class Pair<L> {
private L left;
private int right;
public Pair(L left, int right) {
this.left = left;
this.right = right;
}
public L getLeft() { return left; }
public int getRight() { return right; }
public void ToString() {
System.out.println(left + "," + right);
}
public boolean equals(Pair p) {
return (this.getLeft().equals(p.getLeft()) && this.getRight() == p.getRight());
}
public ArrayList<Pair> neighbors(int rowLimit, int ColumnLimit) {
ArrayList<Pair> neighbors = new ArrayList<Pair>();
Pair neighborL;
Pair neighborR;
Pair neighborU;
Pair neighborD;
if (((int)this.left-1 >= 0)) {
neighborU = new Pair((int)this.left-1, this.right);
// neighborU.ToString();
neighbors.add(neighborU);
}
if ((int)this.left+1 < rowLimit) {
neighborD = new Pair((int)this.left+1, this.right);
// neighborD.ToString();
neighbors.add(neighborD);
}
if ((int)this.right-1 >= 0) {
neighborL = new Pair((int)this.left, this.right-1);
// neighborL.ToString();
neighbors.add(neighborL);
}
if ((int)this.right+1 < ColumnLimit) {
neighborR = new Pair((int)this.left, this.right+1);
// neighborR.ToString();
neighbors.add(neighborR);
}
return neighbors;
}
}
I'm storing Pairs as keys in a hashmap like this:
Map<Pair, Integer> costSoFar = new HashMap<Pair, Integer>();
costSoFar.put(sLocale, 0);
When I run the line below, which is to say, if the key is not in the hashmap:
if (!costSoFar.containsKey(next))
It evaluates to true, even when I know the key is in there, as I've checked through debugging.
If anyone can help clear up why the hashmap isn't recognizing the keys it'd be much appreciated. Perhaps my equals method isn't up to scratch?
Why are you using Generics if L seems to be int too?
Replace your equals:
public boolean equals(Object o) {
if (o instanceof Pair){
Pair p = (Pair)o;
return (this.getLeft().equals(p.getLeft()) && this.getRight() == p.getRight());
}
return false;
}
And implement int hashCode():
public int hashCode() {
return this.getLeft() * 31 + this.getRight();
}
Method containsKey(Object) in java.util.HashMap use the java.util.HashMap.getEntry(Object) which call hashCode() to obtain the hashCode for the Key and use it to retrive the object. You need to override java.lang.Object.hashCode() to make your code properly work.

How to compare Generic type and non-generic type values in java?

The following code is checking whether the given binary tree is a binary search tree or not which is well-known code.
But the problem is Node class has a generic type value.
Thus the following codes occurs errors since it compares generic type T and non-generic type int. I've tried this and that but I couldn't find the solution. I cannot use compareTo() either in this case.
(Of course if I change the Node class to have int value, but I don't want to change the Node class like this.)
Any thought or idea?
public class Node<T> {
Node<T> left;
Node<T> right;
T value;
public Node(T value) {
this.value = value;
this.left = null;
this.right = null;
}
public boolean BTisBST(Node<T> root) {
if(root == null)
return false;
return BTisBST(root, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
public boolean BTisBST(Node<T> root, int min, int max) {
if(root == null)
return true;
if(min > root.value || root.value > max )
return false;
return BTisBST(root.left, min, root.value && BTisBST(root.right, root.value + 1, max);
}
The easiest solution is to change your template type,
// Now take any type(s) that are Comparable.
public class Node<T extends Comparable<T>> {
}

How do I calculate the number of "only child"-nodes in a binary tree?

NOTICE: this is homework-related, but I'm not tagging it as such because the 'homework' tag is marked as obselete (?)
Using the following class that implements a binary tree...
class TreeNode
{
private Object value;
private TreeNode left, right;
public TreeNode(Object initValue)
{
value = initValue;
left = null;
right = null;
}
public TreeNode(Object initValue, TreeNode initLeft, TreeNode initRight)
{
value = initValue;
left = initLeft;
right = initRight;
}
public Object getValue()
{
return value;
}
public TreeNode getLeft()
{
return left;
}
public TreeNode getRight()
{
return right;
}
public void setValue(Object theNewValue)
{
value = theNewValue;
}
public void setLeft(TreeNode theNewLeft)
{
left = theNewLeft;
}
public void setRight(TreeNode theNewRight)
{
right = theNewRight;
}
}
I need to calculate the number of nodes in the binary tree that are "only children," this being defined as a node that doesn't have another node stemming from its parent.
This is what I have so far:
public static int countOnlys(TreeNode t)
{
if(t == null)
return 0;
if(isAnOnlyChild(t))
return 1;
return countOnlys(t.getLeft()) + countOnlys(t.getRight());
}
I don't know how to implement the boolean method isAnOnlyChild(TreeNode t)
Could someone please help me?
You are pretty close and have the traversal looking good but in your Treenode you do not have a link between a child and its parent. So You can not tell from say a left child if a sibling (right child) exists.
You could have a parent Treenode (along with left and right) so you could check how many children a given node's parent has. Or as ajp15243 suggested, instead use a method that checks how many children a given node has.
Some pseudo code of the latter:
//we still need to check if that only child has its own children
if hasOnlyChild(t)
return 1 + checkOnlys(left) + checkOnlys(right)
else
return checkOnlys(left) + checkOnlys(right)
As you have already noticed, one solution is to count number of parents that have only one child. This should work:
public static int countOnlys(TreeNode t)
{
if(t == null || numberOfChildren(t)==0){
return 0;
}
if(numberOfChildren(t)==1){
return 1+ countOnlys(t.getLeft()) + countOnlys(t.getRight());
}
if(numberOfChildren(t)==2 ){
return countOnlys(t.getLeft()) + countOnlys(t.getRight());
}
return 0;
}
public static int numberOfChildren (TreeNode t){
int count = 0;
if(t.getLeft() != null ) count++;
if(t.getRight() != null) count++;
return count;
}
A parent has an only child if exactly one of the children is non-null (which implies that exactly one of its children is null):
((t.getLeft() == null || t.getRight() == null)) && !(t.getLeft() == null && t.getRight() == null)
You don't test, however, the node when you visit it as the recursive code traverses the tree. (This is similar to the Visitor pattern.) What you do is test for an only child when you are sitting on the parent. It's actually a logical exclusive-or test because one and only one of the children needs to be non-null to detect that this node has an only child.
So the algorithm is to
visit each node in the tree.
count it, if the node has only one child
That's it. The rest is plumbing.
public static int onlyChild(TreeNode t){
int res = 0;
if( t != null){
// ^ means XOR
if(t.getLeft() == null ^ t.getRight() == null){
res = 1;
}
res += onlyChild(t.getLeft()) + onlyChild(t.getRight()));
}
return res;
}
whenever you traverse a binary tree, think recursively. this should work.
public static int countOnlys(TreeNode t)
{
if(t == null)
return 0;
if (t.getLeft()==null&&t.getRight()==null)
return 1;
return countOnlys(t.getLeft())+countOnlys(t.getRight());
}
public int countNode(Node root) {
if(root == null)
return 0;
if(root.leftChild == null && root.rightChild == null)
return 0;
if(root.leftChild == null || root.rightChild == null)
return 1 + countNode(root.leftChild) + countNode(root.rightChild);
else
return countNode(root.leftChild) + countNode(root.rightChild);
}

Categories

Resources