Comparable<T> in a Boolean isBST - java

So I understand what is going on inside of this method but am totally lost on how to write it. when i run this method i get with in my program i get. compareTo(T) in java.lang.Comparable cannot be applied to (java.lang.Comparable) on the BOLDED lines so hopefully you can point out what it is without me having to post all the different c;asses with it.
public boolean isBST(BinaryTreeNode<T> tree){
Comparable<T> temp1 = (Comparable<T>) tree.lLink.info;
Comparable<T> temp2 = (Comparable<T>) tree.rLink.info;
Comparable<T> temp3 = (Comparable<T>) tree.info;
if (tree == null)
return true;
else if (tree.lLink != null) // && tree.lLink.info > tree.info)
return false ;
**else if ( temp1.compareTo(temp3) > 0 )**
return false;
else if (tree.rLink != null) // && tree.rLink.info <= tree.info)
return false;
**else if ( temp2.compareTo(temp3) > 0 )**
return false;
else
return isBST(tree.lLink) && isBST(tree.rLink);
}//closes boolean isBST

Related

Java Treemap comparator ignoring get when key is different instances

The issue I'm having is that the get method throws NPE when the key is a different instance than the one in the TreeMap.
public class ConjuntDocuments {
private TreeMap<Capcalera, Document> almacen;
private ArrayList<Pair_plantilla> plantilla;
ConjuntDocuments() {
almacen = new TreeMap<Capcalera, Document>(new CustomComparator());
plantilla = new ArrayList<Pair_plantilla>();
}
private static class CustomComparator implements Comparator<Capcalera> {
#Override
public int compare(Capcalera c1, Capcalera c2) {
int ax = c1.get_tit().get_nom().compareFrase(c2.get_tit().get_nom());
if (ax < 0) return -1;
else if (ax > 0) return 1;
//titols iguals
else {
ax = c1.get_au().get_nom().compareFrase(c2.get_au().get_nom());
if (ax < 0) return -1;
else if (ax > 0) return 1;
}
//titols i autors iguals
return 0;
}
}
compareFrase compares ArrayLists(Paraula) -> Frase, Paraula is like a string, get_chars returns a String.
public int compareFrase(Frase f) {
for(int i=0; i<min(this.get_size(), f.get_size()); ++i){
int aux = this.get_paraula(i).get_chars().compareTo(f.get_paraula(i).get_chars());
if(aux < 0) return -1;
else if(aux > 0) return 1;
}
if(this.get_size() < f.get_size()) return -1;
else if(this.get_size() > f.get_size()) return 1;
return 0;
}
Titol and autor are Frases -> ArrayList(Paraula)
public class Capcalera {
private Titol tit;
private Autor au;
So after trying to figure this out, I've realised that the get method only works if the key referenced is the same instance than the one mapped, right after putting an entry (almacen.put(capcalera,document) , if I try to call almacen.get(Capcalera) it will return the value correctly, but if I create a new Capcalera, it will throw NPE. I'm assuming there is an issue with the comparator but since the entries are sorted correctly I can't figure out what is wrong.
EDIT:
I've implemented .equals and .hashcode from Capcalera, but I might be doing something wrong because .get from the Treemap still throws NPE.
#Override
public int hashCode() {
int hashTitol = tit != null ? tit.hashCode() : 0;
int hashAutor = au != null ? au.hashCode() : 0;
return (hashTitol + hashAutor) * hashAutor + hashTitol;
}
#Override
public boolean equals(Object other) {
if (other instanceof Capcalera) {
Capcalera otherCapcalera = (Capcalera) other;
return
(( this.get_tit().get_nom().equalsFrase(otherCapcalera.get_tit().get_nom()) ||
( this.get_tit() != null && otherCapcalera.get_tit() != null &&
this.get_tit().get_nom().equalsFrase(otherCapcalera.get_tit().get_nom()) )) &&
( this.get_au().get_nom().equalsFrase(otherCapcalera.get_au().get_nom()) ||
( this.get_au() != null && otherCapcalera.get_au() != null &&
this.get_au().get_nom().equalsFrase(otherCapcalera.get_au().get_nom()))) );
}
return false;
}
equalsFrase returns true if Titol/Autor are equals
public boolean equalsFrase(Frase f) {
for(int i=0; i<min(this.get_size(), f.get_size()); ++i){
int aux = this.get_paraula(i).get_chars().compareTo(f.get_paraula(i).get_chars());
if(aux < 0) return false;
else if(aux > 0) return false;
}
if(this.get_size() < f.get_size()) return false;
else if(this.get_size() > f.get_size()) return false;
return true;
}

Check if two trees are identical

I've made my own Tree class and I trying to check if two trees are identical. But the problem here is I'm using this call :
Tree myTree = new Tree();
Tree mySecondTree = new Tree();
myTree.isIdentical(myTree, mySecondTree);
It's kind of odd to pass it this way, I want to pass it this way :
myTree.isIdentical(mySecondTree);
isIdentical function :
class Tree<T>{
T data;
Tree left;
Tree right;
Tree(T data){
this.data = data;
}
public boolean isIdentical(Tree t1, Tree t2){
if(t1 == t2)
return true;
if(t1==null || t2==null)
return false;
return (
(t1.data == t2.data) &&
(isIdentical(t1.left, t2.left)) &&
(isIdentical(t1.right, t2.right))
);
}
}
I tried using Stack, but I'm kind of stuck on this
Since you want to execute it this way
myTree.isIdentical(mySecondTree);
You could do this
public boolean isIdentical(Tree t2){
Tree t1 = this;
return isIdentical(t1, t2);
}
private boolean isIdentical(Tree t1, Tree t2){
if(t1 == t2)
return true;
if(t1==null || t2==null)
return false;
return (
(t1.data == t2.data) &&
(isIdentical(t1.left, t2.left)) &&
(isIdentical(t1.right, t2.right))
);
}
Your data-structure allows you to call the modified isIdentical(Tree<T>) method in the left and right child nodes after a few checks. Remember that the parent, right-child and left-child are all different Tree node instances in your code.
public boolean isIdentical(Tree<T> that) {
if (this == that)
return true;
if (that == null)
return false;
//check the equality of the current node's data for both this and that.
if (this.data == that.data || (this.data != null && this.data.equals(that.data))) {
//check the left hand side of the current node for both this and that.
if ((this.left == null && that.left == null
|| this.left != null && this.left.isIdentical(that.left))
//check the right hand side of the current node for both this and that.
&& (this.right == null && that.right == null
|| this.right != null && this.right.isIdentical(that.right))) {
return true;
}
}
return false;
}
You could stay with a recursion and make isIdentical(myTree, Othertree) private. Then wrap it inside a method IsIdentical(otherTree) that calls the method with two arguments suppling this (refrence to the current object) as the first parameter.

Recursive compare two binary search trees

I need to compare two binary search trees and see if they are equal or not.
I developed following code that uses recursion.
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
if(n1.getNodeData() != n2.getNodeData())
return false;
else
{
if(n1.left != null && n2.left != null)
compareTrees(n1.left, n2.left);
if(n1.right != null && n2.right != null)
compareTrees(n1.right, n2.right);
}
return true;
}
The problem is that if two nodes are not equal, the method will return false but because I use recursion, the return value will be overridden to true no matter what. I have been stuck with this problem for all day and nothing worked for me. I searched online but I didn't find anything relevant to my code.
Is there any way to break from all nested methods and return value to the first method?
You need to return the result of the subtree comparison:
boolean b1, b2;
if(n1.left != null && n2.left != null)
b1 = compareTrees(n1.left, n2.left);
if(n1.right != null && n2.right != null)
b2 = compareTrees(n1.right, n2.right);
return b1 && b2;
But why not just deal with nulls before-hand?
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
if (n1 == null || n2 == null)
return n1 == n2; // i.e. both null
if (n1.getNodeData() != n2.getNodeData())
return false;
return compareTrees(n1.left, n2.left) && compareTrees(n1.right, n2.right);
}
I would do it changing the order:
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
boolean equalLeft = false;
boolean equalRight = false;
if(n1.getNodeData() == n2.getNodeData())
{
if(n1.left != null && n2.left != null){
equalLeft = compareTrees(n1.left, n2.left);
} else{
equalLeft = true;
}
if(n1.right != null && n2.right != null){
equalRight = compareTrees(n1.right, n2.right);
} else{
equalRight = true;
}
return equalLeft && equalRight;
} else{
return false;
}
}
Try to face the problem avoiding null values and using equals() method instead of == comparison for your nodes. I shoud do it this way:
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2){
//avoid nulls :TDD
if (n1==null && n1==n2)
return true;
if ((n1==null && n2!=null) || (n2==null && n1!=null))
return false;
//ensure logic without nulls, comparing with equals() method
boolean areEquals = n1.getNodeData().equals(n2.getNodeData());
//compare left
areEquals = areEquals && compareTrees(n1.left, n2.left);
//if still equals, compare right
if(areEquals) areEquals = areEquals && compareTrees(n1.right, n2.right);
return areEquals;
}
Effectively, your code could reduce to:
private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
if(n1==null || n2==null) return n1==n2;
return (n1.getNodeData()==n2.getNodeDate()) && compareTrees(n1.left, n2.left) && compareTrees(n1.right, n2.right)
}
I will tell you couple of problems your code has.
Termination criteria when root is null (it will always happen in the end).
Return statements in recursive calls. You are always returning the true in the end.
PS: If you add NULL checks (explained in 1), you need not to add null checks in the subsequent recursive calls. Now the second half of your code will look like:
return compareTrees(n1.left, n2.left) && compareTrees(n1.right, n2.right);

Java - modified compareTo method says it needs to return an int, but it should be returning one

I'm learning basic Java right now and have a problem with my code that I can't figure out. It's basically what the title says. My Java compiler is telling me that there's an error with my custom compareTo method, saying that it needs to return an int. The problem is, as far as I can tell, it IS returning an int. Yet it's still giving me an error. Could someone please point out in my code what's wrong? And also I have already implemented Comparable in my class. Here's my method:
public int compareTo(Homework other) {
if (getDaysLate() < other.getDaysLate()) {
return -1;
} else if ((dateSubmitted == other.dateSubmitted)
&& (files.compareTo(other.files) == -1)) {
return -1;
} else if ((dateSubmitted == other.dateSubmitted)
&& (files == other.files)) {
if (name.compareTo(other.name) == -1) {
return -1;
} else if (name.compareTo(other.name) == 1) {
return 1;
} else if (name.compareTo(other.name) == 0) {
return 0;
}
} else {
return 0;
}
}
There is a path in the third else that does't return anything.
else if ((dateSubmitted == other.dateSubmitted) && (files == other.files)) {
if (name.compareTo(other.name) == -1) {
return -1;
}
else if (name.compareTo(other.name) == 1) {
return 1;
}
else if (name.compareTo(other.name) == 0) {
return 0;
} else return ...
}
BTW, I'm not sure if I'm following the logic of your implementation, since it seems that you are returning 0 if dateSubmitted != other.dateSubmitted. compareTo should also be anti-symetric (i.e. sgn(x.compareTo(y)) == -sgn(y.compareTo(x))), but your implementation is not.
How can you be sure (with all these if and else) that you are always returning an int? It does not seem so obvious to me and aparently the compiler agrees with me too.
One way to solve this (probably not the best one) is to add a return -1; //or whatever value at the end of your function.
In your second else-if statement you have a code path that may not return anything. You say:
else if ((dateSubmitted == other.dateSubmitted) && (files == other.files)) {
if (name.compareTo(other.name) == -1) {
return -1;
}
else if (name.compareTo(other.name) == 1) {
return 1;
}
else if (name.compareTo(other.name) == 0) {
return 0;
}
, but what if none of those else if's are true? Try changing the last else-if in your second else-if statement to else.
You are missing an else after this branch:
else if (name.compareTo(other.name) == 0) {
return 0;
}
If the test fails (compareTo doesn't return 0) the method would have to exit without a return value, which is illegal in Java.
Also, compareTo may return any integer value, not only 0, 1, and -1.
The method should return appropriate value on all code flow paths; in other words, on all conditions when the method returns. In the following if block it does not return on one path that I've marked.
else if ((dateSubmitted == other.dateSubmitted) && (files == other.files)) {
if (name.compareTo(other.name) == -1) {
return -1;
}
else if (name.compareTo(other.name) == 1) {
return 1;
}
else if (name.compareTo(other.name) == 0) {
return 0;
}
// It should return something here, if none of the above "if" statements match.
// Or one of the above "else if" should be changed to "else"
}

Interval intersection

I wrote a class that checks whether two integer intevals overlap.
However I don't like this solution to much. I think that it's possible to do it in a better and simpler way.
public class IntegerInterval implements Interval {
private Integer start;
private Integer end;
public IntegerInterval(Integer start, Integer end) {
this.start = start;
this.end = end;
}
public Integer getStart() {
return start;
}
public Integer getEnd() {
return end;
}
public boolean isOverlapping(IntegerInterval other) {
if (other != null) {
return isInInterval(start, other) || isInInterval(end, other)
|| isInInterval(other.start, this) || isInInterval(other.end, this);
}
return false;
}
public boolean isInInterval(Integer number, IntegerInterval interval) {
if (number != null && interval != null) {
if(interval.getStart() == null && interval.getEnd() != null) {
return number.intValue() <= interval.getEnd().intValue();
}
if(interval.getStart() != null && interval.getEnd() == null) {
return number.intValue() >= interval.getStart().intValue();
}
if(interval.getStart() == null && interval.getEnd() == null) {
return true;
}
return interval.getStart() <= number && number <= interval.getEnd();
}
else if(number == null && interval != null) {
return interval.getStart() == null && interval.getEnd() == null;
}
return false;
}
}
The following code should be simpler:
public boolean isOverlapping(IntegerInterval other) {
if (other == null) return false; // for readability's sake, this condition is pulled out
// overlap happens ONLY when this's end is on the right of other's start
// AND this's start is on the left of other's end.
return (((this.end == null) || (other.start == null) || (this.end.intValue() >= other.start.intValue())) &&
((this.start == null) || (other.end == null) || (this.start.intValue() <= other.end.intValue())));
}
UPDATE If compare by Date as #Adam actually asked, the code would be:
private static boolean dateRangesAreOverlaping(Date start1, Date end1,
Date start2, Date end2) {
return (((end1 == null) || (start2 == null) || end1.after(start2)) &&
((start1 == null) || (end2 == null) || start1.before(end2)));
}
You should wrap start and end in a specific Comparable class that is able to encapsulate null. This way you only need to invoke compareTo in isInInterval and don't need to bother with null.
That class could also explicitly represent positive and negative infinity.
EDIT:
If you add a type parameter <T extends Comparable<T>> to the class declaration and declare the types of start and end type as Comparable<T> then you can use any type that implements Comparable with your Interval, not only Integer.
Assuming start < end. There should be 3 the checks for position of start relative to other: left, middle and right (right is for completeness as there is no intersection possible). So here are 2 remaining checks:
(start <= other.start && end >= other.start) ||
(start >= other.start && start <= other.end)
// start > other.end means no intersection as end > start > other.end
If you do checks for location of start as if than second chech can be just (start <= other.end):
if (start <= other.start) return end >= other.start;
else if (start <= other.end) return true;
else return false;
Adjust "=" portions for your needs and add you null checks appropriately (i.e. use SpaceTrucker answer to make comaprison with null hidden inside class).

Categories