This is what I have to do. The Binary Search Tree ADT is extended to include a bool ean method si m i l ar Trees that receives references to two binary trees and determines whether the shapes of the trees are the same. (The nodes do not have to contain the same values, but each node must have the same number of children.) I have code to show what I have.
public static <T> boolean similarTrees(BSTNode<T> a, BSTNode<T> b) {
// check for reference equality and nulls
if (a == b) return true; // note this picks up case of two nulls
if (a == null) return false;
if (b == null) return false;
// check for data inequality
if (a.data != b.data) {
if ((a.data == null) || (b.data == null)) return false;
if (!(a.data.equals(b.data))) return false;
}
// recursively check branches
if (!similarTrees(a.left, b.left)) return false;
if (!similarTrees(a.right, b.right)) return false;
// we've eliminated all possibilities for non-equality, so trees must be equal
return true;
}
Related
I am iterating over two collections and check if both collections contain
the same elements. I can't use Java 8.
edit 1 year after:
I created the method in the question to check if two Collections contain the same elements, without thinking about the fact that I am passing two Collection implementations into the method.
But Collection does not determine how elements are sorted. And I am iterating over the collections. Thus, some implementation of Collection could save elements in random order, while containing the same elements.
Both collections contain elements that are comparable and the content
is defined as equal, if all elements return a x.compareTo(y) with 0.
Two values are defined as different, if one of them is null, but not the other.
I want to find an elegant way to compare on nullity and prevent
a null check on the final compareTo().
My current implementation:
public static <T extends Comparable<T>> boolean isSame(#Nullable Collection<T> a, #Nullable Collection<T> b) {
if (a == null || b == null) {
return (a == null && b == null);
}
if (a.size() != b.size()) {
return false;
}
Iterator<T> aIt = a.iterator();
Iterator<T> bIt = b.iterator();
while (aIt.hasNext()) {
T aValue = aIt.next();
T bValue = bIt.next();
if (aValue == null || bValue == null) {
if (aValue == null ^ bValue == null) {
return false;
}
//both null, don't compare, continue looping...
} else if (aValue.compareTo(bValue) != 0) {
return false;
}
}
return true;
}
I want to continue the while loop, if both values are null, because that is
defined as equal.
But I am struggling with this part:
if (aValue == null || bValue == null) {
if (aValue == null ^ bValue == null) {
return false;
}
}
Question:
Is there a more elegant and readable way to compare on nullity, do a further compare if both are not null, return false if only one is null, and continue the loop, if both values are null?
The sequence as follows should work well:
if(aValue == null && bValue == null) continue; // both null; continue
if(aValue == null || bValue == null) return false; // any null; return false
if(aValue.compareTo(bValue) != 0) { // both non-null; compare
return false;
}
In Java8, you can build a Comparator that would replace comparison sequence at cost of creating an extra object (you will need to decide if you care about that):
Comparator<T> cmp = Comparator.nullsLast(Comparator.naturalOrder());
The compararor will take care of null comparison for you (since you assume that two nulls are equal):
while (aIt.hasNext()) {
T aValue = aIt.next();
T bValue = bIt.next();
if (cmp.compare(aValue, bValue) != 0) {
return false;
}
}
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.
This question is sort of a follow up to Implementing hashCode for a BST. My question was poorly thought through and so I got an answer that I am not sure how to use.
I need to implement equals for a BST: so that iff two BSTs are equal in structure and content, then equals returns true. As such, I imagine I also need to implement the hashCode function. I got the answer for the hashCode function such that the trees are equal in structure and content.
#Override
puclic int hashCode(){
int h = Objects.hashCode(data);//data is int
int child=0;
if(null != left)
child =left.hashCode();
if(null != right)
child+= right.hashCode();
if(0<child) h= h*31+child;
return h;
}
But then how do I implement the equals function? Will the following work iff the trees are equal in both structure and content?
#Override
public boolean equals(Node otherRoot){
return root.hashCode() == otherRoot.hashCode();
}
Might there be circumstances where I can false positives?
Or should my hashCode be
#Override
public int hashCode(){
int h = contents.hashCode();
h = h * 31 + Objects.hashCode(leftChild);
h = h * 31 + Objects.hashCode(rightChild);
return h;
}
and in this latter case, would my equals avoid false positives?
Will the following work iff the trees are equal in both structure and content? root.hashCode() == otherRoot.hashCode()
No, it would not work, because hash code equality is a one-way street: when objects are equal, hash codes must be equal. However, when objects are not equal, hash codes may or may not be equal. This makes sense once you apply a pigeonhole principle: the number of possible hash codes is about 4B, while the number of possible BSTs is virtually infinite.
You can build a comparison in the same way that you built the hash code - i.e. recursively:
Check if the values at the nodes being compared are equal to each other. If the values are different, return false
Check if both nodes have a left subtree. If one of them has a left subtree and the other one does not, return false
Check if both nodes have a right subtree. If one of them has a right subtree and the other one does not, return false
Apply equals recursively to left subtrees. If the result is false, return false
Apply equals recursively to right subtrees. If the result is false, return false
Return true
Not sure what Objects is, but your last hashCode() example needs to handle null, I would think something like:
#Override
public int hashCode() {
int h = contents.hashCode();
if (leftChild != null) h = h* 31 + leftChild.hashCode();
if (rightChild != null) h = h * 31 + rightChild.hashCode();
return h;
}
I can see overflowing h if the tree is deep enough, with all the h * 31.
The contract for hashCode does not guarantee equality, so you probably need to call equals all the way down the tree to make sure everything balances out.
I haven't tested this exactly but here's somewhere to start
public boolean equals(Object o) {
// exact same object
if(this === o) {
return true;
}
if(!o instanceof Node) {
return false
}
Node otherTree = (Node) o;
boolean selfHasLeft = this.left == null,
selfHasRight = this.right == null,
otherHasLeft = otherTree.left == null,
otherHasRight = otherTree.right == null;
// this tree must have the same children as the other tree
if(selfHasLeft != otherHasLeft || selfHasRight != otherHasRight) {
return false;
}
// must have same value
if(this.value != other.value) {
return false;
}
// if they have no children then now they should be the same tree
// otherwise, check that their children are the same
if(!selfHasLeft && !selfHasRight) {
return true;
} else if(selfHasLeft && !selfHasRight) {
return this.left.equals(otherTree.left);
} else if(selfHasRight && !selfHasLeft) {
return this.right.equals(otherTree.right);
} else {
return this.left.equals(otherTree.left) && this.right.equals(otherTree.right);
}
}
Your second hashCode implementation looks good to me, but you can never avoid hashcode collisions when the number of possible objects are greater than the range of an int - which is the case here so you should not use the hashcode in equals.
What you should do is something like this (assuming the class name is BST):
public boolean equals(Object other) {
if(this == other) {
return true;
}
if(!(other instanceof BST)) {
// If other is null we will end up here
return false;
}
BST bst = (BST) other;
// Check equality of the left child
if(left != null) {
if(!left.equals(other.left)) {
// Left childs aren't equal
return false;
}
} else if (other.left != null) {
// this.left is null but other.left isn't
return false;
}
// Check equality of the right child
if(right != null) {
if(!right.equals(other.right)) {
// Right childs aren't equal
return false;
}
} else if (other.right != null) {
// this.right is null but other.right isn't
return false;
}
// Both left and right childs are equal
return true;
}
I am writing a code and am following all instructions given to me. All the codes and methods look fine when I run the program but the equal method! Based on the instructions, I am supposed to get false when the tested asks if point (a, b)---(c, d) is equals to (e, f)---(g, h), but I get true. Can Anyone give me an idea where I am doing wrong?
Thank you in advance!
/**
* The equals method should return true if the given object is equal to the
* the Object passed in. Note that this method receives an Object; there is
* a particular way that this method should be implemented (see notes from class).
*
* Notice that two Segments are equal even if their endpoints are swapped
* i.e.: (1, 2)---(3, 4) == (3, 4)---(1, 2)
*/
public boolean equals(Object obj) {
//if (obj instanceof Segment) {
//Segment other = (Segment) obj;
//return p1 == other.getP1() && p2 == other.getP2();
//}
//else {
//throw new IllegalArgumentException("undefined");
//}
if(obj == null)
return false;
if(this == obj)
return true;
if(!(obj instanceof Segment))
return false;
else if(obj.getClass() != this.getClass()){
return false;
}
else
{
Segment S = (Segment)obj;
if(this.getP1() == S.getP1() &&
this.getP2() == S.getP2());
return true;
//else if(obj.getP1() != this.getP1() &&
// obj.getP2() != this.getP2());
// return false;
}
}
if(this.getP1() == S.getP1() &&
this.getP2() == S.getP2());
^
Take out this semicolon.
Then you will also need to return a value if the if statement isn't met.
Edit
Currently your if statement is serving no purpose. Take out the semicolon so that the following return statement is qualified by the if. Then after that add a return false that will be applied if the if statement isn't met.
Like this:
if (this.getP1()==S.getP1() && this.getP2()==S.getP2()) {
return true;
}
return false;
Or, put more simply:
return (this.getP1()==S.getP1() && this.getP2()==S.getP2());
I have a List (actually a LinkedList) and I add Items to it which implement the equals-method.
The problem is that I add items that are equal, but not identical (like two initialized objects). Now, when I want to get the index of the item I added second, I get, of course, the element of the first item, because indexOf searches for equality and not identity.
I tried to create my own subclass of LinkedList and overwrite the indexOf-method, but this is not possible, because I don't have access to neither the subclass Node nor the Node-Element first.
Here is an example:
public class ExampleObject {
int number;
public ExampleObject(){
number = 0;
}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
ExampleObject other = (ExampleObject) obj;
if (number != other.number) return false;
return true;
}
public static void main(String[] args) {
LinkedList<ExampleObject> list = new LinkedList<ExampleObject>();
ExampleObject one = new ExampleObject();
ExampleObject two = new ExampleObject();
list.add(one);
list.add(two);
System.out.println(list.indexOf(one)); // '0' as expected
System.out.println(list.indexOf(two)); // '0', but I want to get '1'
}
}
My intention: I need a list of objects, where I want to store initialized objects and edit them later.
Do the iteration yourself, indexOf is just a helper method:
static int indexOfById(List<?> list, Object searchedObject) {
int i = 0;
for (Object o : list) {
if (o == searchedObject) return i;
i++;
}
return -1;
}
There are several solutions to this problem.
1) The correct solution: If you need identity comparison, then you should not override the equals method. You told us that you must override it, as you need it in another place. That indicates a design problem in your software, and you really should solve this.
2) Have a look at the class sun.awt.util.IdentityLinkedList. This is nearly a "normal" LinkedList with the identity behavior for the indexOf method. If you do not want to rely on a class in a sun sub-package, you can copy the code into a class that resides in your packages.
3) You could follow a procedural solution with iterating the list yourself:
public static <E> int indexOf(List<E> list, E searchItem) {
int index = 0;
for (E item : list) {
if (item == searchItem)
return index;
index += 1;
}
return -1;
}
4) Write a wrapper for your objects.
public class IdentityWrapper {
public Object item;
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
IdentityWrapper other = (IdentityWrapper) obj;
return item == other.item;
}
}
Then use this wrapper in your list: LinkedList<IdentityWrapper>. Note, that I provided a public item field in the wrapper. Normally, I would do it with a constructor and a private field only.