Comparing circular linkedlists equals method - java

public class LinkedList {
Object contents;
LinkedList next = null;
public boolean equals(Object item) {
return (this == item) || ((item instanceof LinkedList) && this.equals((LinkedList)item));
}
public boolean equals(LinkedList item) {
return myUtil.equals(this.contents, item.contents) && myUtil.equals(this.next, item.next);
}
}
public class myUtil{
public static boolean equals(Object x, Object y) {
return (x == y) || (x != null && x.equals(y));
}
}
main(){
LinkedList myList = new LinkedList();
myList.next = new LinkedList();
LinkedList head = myList.next;
myList.next = head;
}
I think i have created a circular linkedlist here. So what i have done is to overwrite the equals method to ensure that circular references are handled:
For some reason the LinkedList.equals doesnt seem to return...is it because of my circular linkedlist, or am i missing some conditions?

The primary problem with this code is that your comparison will not terminate upon circular reference, and will loop forever if all contents fields are equal. It will always continue to the next comparison, and since the next item is always there (as it's a circle) this will continue forever.
myUtil.equals(this.contents, item.contents) && myUtil.equals(this.next, item.next);
To solve this issue, the simplest method would be to add a boolean private 'visited' field to each List item. When you compare, set visited on each item after the comparison. If both are not visited and the same, then continue. If only one is visited, your lists are not identical. If both are visited, you've compared the reachable entirety of the list. Generally, having loops in your list are a bad idea, and there exist algorithms specifically to detect them. This can be a confusing topic. Here is a coverage of loop detection that may help you understand the issue further. Remember, if you use the visited field, you must unset all of them with another loop in your equals() to allow it to run again.
On another note, you do not initialize the contents field of your list nodes for the test. This is okay here, since they are initialized to null, but generally it is good practice to explicitly initialize all your fields.
Generally speaking, you also don't need the equals(Object item) override. Try
public boolean equals(LinkedList item){
if (this == item){
return true; // It's the same object
}
// Add some null checks here, I'm lazy
if (this.visited && item.visited && this.contents.equals(item.contents){
this.visited = false; //Unset
item.visited = false;
return true;
}
if (this.visited && !item.visited){
this.visited = false;
return false;
}
if (!this.visited && item.visited){
item.visited = false;
return false;
}
if (!this.visited && !item.visited && this.visited.contents.equals(item.contents){
this.visited = true;
item.visited = true;
boolean ret = this.next.equals(item.next);
this.visited = false;
item.visited = false;
return ret;
}
// Contents not equal
return false;
}
This backtracks and unsets with some basic recursion. I obviously haven't compiled this, but that's the gist of it, I think (I hope there aren't too many errors)

Two issues, first you do not have a circular linked list. The follow code creates 2 lists, list1.next = list2, list2.next = null. No circle created.
LinkedList myList = new LinkedList();
myList.next = new LinkedList();
LinkedList head = myList.next;
myList.next = head;
Second, if you DID have a circular linked list, the following would produce an infinite loop since there is no end condition reached this is because in a circular linked linked, next should never be null.
public boolean equals(Object item) {
return (this == item) || ((item instanceof LinkedList) &&
this.equals((LinkedList)item));
}
public boolean equals(LinkedList item) {
return myUtil.equals(this.contents, item.contents) && myUtil.equals(this.next, item.next);
}
To do this effectively you need to provide SOME mechanism to iterate the list in a non-circular fashion even if this mechanism is private and not exposed to other users. One way to do this would be to mark a single node as the "root".

return myUtil.equals(this.contents, item.contents)
&& myUtil.equals(this.next, item.next);
I would imagine that this is your issue as you suspected, when you perform the second expression of the && namely myUtil.equals(this.next, item.next); you enter the myUtil.equals method which performs this line:
return (x == y) || (x != null && x.equals(y));
Which in turn uses x's .equals() method, which will repeat the process for its item.next, and so on and so forth since you have a circularly linked list.

This will cause an infinite loop, this is because in the code:
public static boolean equals(Object x, Object y) {
return (x == y) || (x != null && x.equals(y));
}
The x.equals(y) will again invoke:
public boolean equals(LinkedList item) {
return myUtil.equals(this.contents, item.contents)
&& myUtil.equals(this.next, item.next);
}
But if you are performing myList1.equals(myList1), you will not get an infinite loop because the (x==y) in myUtils.equals() will return true so infinite loop will not happen if you compare same objects.
However when you compare different objects, you will enter into an infinite loop.
This is not a circular list issue, this is because of the code design you've chosen.

Finally completed my equals method implementation. For this I had to use additional checking tools by myself. I can't tell it is effective, but some extraordinary states are checked.
public boolean equals(Object o)
{
if(!(o instanceof CircularlyLinkedList))
return false;
CircularlyLinkedList<E> list=(CircularlyLinkedList<E>)o;
if(this==list)
return true;
if(size()!=list.size())
return false;
//tail element of this object
Node<E> thisTail=tail;
//tail element of list passing as parameter
Node<E> listTail=list.tail;
//checking if tail elements of both lists are the same or not. If not rotate list till equatation is provided for tails
if(!thisTail.equals(listTail))
{
listTail = equate(list);
if(listTail==null)
return false;
}
//Each element checking
for(int i=0; i<size(); i++)
{
thisTail=thisTail.next;
listTail=listTail.next;
if(!thisTail.equals(listTail))
{
listTail = equate(list);
listTail=tail;
i=0;
if(listTail==null)
return false;
}
}
return true;
}
And equate method:
private Node<E> equate(CircularlyLinkedList<E> list)
{
Node<E> thisTail=tail;
Node<E> listTail;
for(int i=0; i<list.size(); i++)
{
list.rotate();
listTail=list.tail;
//If full rotation completes then returns null
if(list.getRotation()==0)
{
return null;
}
if(thisTail.equals(listTail))
{
return nodeList;
}
}
return null;
}
getRotation method returns count of rotation operation and changes between 0 and size-1. I hope that it will become useful.

Related

How can I check if two lists are equals?

I have to solve one problem, I don't know the reason why my code doesn't work.
I have to check if two lists I created are completely equals so they have the same value at the same position.
I'm allowed to use loops as well, even by I prefer the recursive mode.
Thank you so much for your help and time!
public static boolean checkEquality(Node n, Node m) {
if(n != null && m != null) {
boolean res = false;
while(n!=null) {
if(n.getElem()==m.getElem()) {
n = n.getNext();
m = m.getNext();
res = true;
}
else
{
res = false;
}
}
return res;
}
else
{
System.out.println("Lists empty!");
return true;
}
}
There are a couple of weak spots, so I give the solid solution:
public static boolean checkEquality(Node n, Node m) {
while (n != null && m != null) {
//if (!Objects.equals(n.getElem(), m.getElem())) {
if (n.getElem() != m.getElem()) {
return false;
}
n = n.getNext();
m = m.getNext();
}
return n == null && m == null;
}
Comparing can only be done while both n and m are not null. Your code only checks n.
== is not valid for instance for String. Instead of .equals one might also use Objects.equals which also tests for null.
getNext in every loop step.
two empty lists are also equal. Both lists should end at the same time.
The tst fails as soon as two compared nodes are not equal. So one should start with assuming a true result. And as soon as the comparison fails, one should no longer loop and certainly not overwrite res from false to true.
it would help if you elaborate what type of list u are comparing,
linkedlist or arrays. based on your function, it seems that you are planning to compare a linkedlist.
linkedlist documentation
arrays documentation
// sample comparison
boolean areIdentical(Node a_head, Node b_head) {
Node a = a_head, b = b_head;
while (a != null && b != null) {
if (a.data != b.data)
return false;
/* If we reach here, then a and b are not null
and their data is same, so move to next nodes
in both lists */
a = a.next;
b = b.next;
}
// If linked lists are identical, then 'a' and 'b'
// must be null at this point.
return (a == null && b == null);
}

LinkedList removeLastOccurrence

I am new to computer science, so forgive my ignorance. For the LinkedList that is in Java,
does the removeLastOccurrence method use the equals method between the object passed in or does it simply compare the memory location?
According to http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/LinkedList.java, the source for that method is:
public boolean removeLastOccurrence(Object o) {
if (o == null) {
for (Node<E> x = last; x != null; x = x.prev) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = last; x != null; x = x.prev) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
Thus if the object you want to remove is null, then it looks for a null value in the list. If the object is not null, then it uses the equals method. However, keep in mind that unless equals is specifically overridden to implement value equality, it will default to identity equality (that is, by comparing memory addresses like == does for objects)

Java: compare two object lists

I'm trying to compare two lists of same objects, those two lists are nodes_cc and nodes_volume. They contains several Node objects. A Node is defined by ID and VALUE. The nodes on the two lists can have common IDs but not common values.
I want to compare the lists like this: I control the first list list (nodes_cc) , if I meet a node that doesn't appear on the second list (nodes_volume), the control MUST stop, even if I will find other nodes that belong even to the second list. I was thinking to use a break so I tried this:
int count=0;
for (int i=0;i<cc_nodes.size();i++){
Node node = cc_nodes.get(i);
for(int j=0;j<volume_nodes.size();j++){
Node node2 = volume_nodes.get(j);
if (node.id==node2.id){
count++;
}
else {
break;
}
}
}
The problem is: the for cycle breaks only after the first check (count is 1), where i'm doing wrong? Can you help fix me this?
You could use some boolean, and check it after your inner for loop :
int count=0;
for (int i=0;i<cc_nodes.size();i++){
Node node = cc_nodes.get(i);
boolean found = false;
for(int j=0;j<volume_nodes.size();j++){
Node node2 = volume_nodes.get(j);
if (node.id==node2.id){
count++;
found = true;
}
}
if(!found)
break;
}
You can Override .equals() and .hashcode() method in Node object to use id as comparator and then :
int count=0;
for (Node node : cc_nodes){
if(volume_nodes.contains(node))
count++;
else
break;
}
You can add this in Node object (if id is int value)
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (id != other.id)
return false;
return true;
}

Why does my function always returns false, even if it finds return true before?

public boolean contains(Object data)
{
Node temp = new Node(data);
Node current = head.getNext();
for(int i = 0; i < size(); i++)
{
//System.out.println(current.getData());
if(temp.getData() == current.getData())
{
System.out.println("true");
return true;
}
else
{
current = current.getNext();
}
}
return false;
}
My code is above and it returns false no matter what. If it finds a true condition, it prints "true" and it still returns false. What am I doing wrong here? I have exact same function, except it's returning an integer instead of boolean and it works perfectly fine with the same method/code.4
My function which does the same and works fine:
public int indexOf(Object data)
{
Node temp = new Node(data);
Node current = head.getNext();
for(int i = 0; i < size(); i++)
{
if(temp.getData() == current.getData())
{
return i;
}
current = current.getNext();
}
return -1;
}
You've got an issue with this expression:
if(temp.getData() == current.getData())
It's bad enough that your data is represented by Object - it really should be a parameterized type* instead. But, since you're using ==, you're checking to see if the object is the same instance, not if they're equivalent.
Change your comparison to use .equals instead.
if(temp.getData().equals(current.getData())
*: In case you were wondering, you'd change your Node to a Node<T> instead, change your linked list instance to be typed to LinkedList<Node<T>>, and change the method argument of contains to be public boolean contains(T data).

contains function linkedlist

public class state implements Comparator<state>{
Point a;
Point b;
private int path_cost=0;
...
}
class Point {
int x;
int y;
...
}
for above i have:
PriorityQueue<state> openNode= new PriorityQueue<state>();
LinkedList<state> closed =new LinkedList<state>();
state currNode;
I need to check if the Point a of ANY openNode or closed equals currNode's Point a.
I could use contains if i had to match the entire object but here i just care about one variabale (Point a) of state class. I want the method to check all the nodes in PriorityQueue and LinkedList.
addition:
I am thinking about using Iterator on my priorityQueue and LinkedList. But i am not sure how to read the value of Point a using Iterator.
EDIT: Looked like I'd misunderstood slightly. It's simpler than I thought.
// I've assumed more conventional names
Point currPoint = currNode.getPointA();
for (State openNode : openNodes) {
if (openNode.getPointA().equals(currPoint)) {
return true;
}
}
for (State closedNode : closedNodes) {
if (closedNode.getPointA().equals(currPoint)) {
return true;
}
}
// No matching points
return false;
You could potentially use Guava's Iterables.concat() method to make this slightly simpler:
for (State node : Iterables.concat(closedNodes, openNodes)) {
if (node.getPointA().equals(currPoint)) {
return true;
}
}
return false;
If you need to know which node has an equal point A, just change it to:
for (State node : Iterables.concat(closedNodes, openNodes)) {
if (node.getPointA().equals(currPoint)) {
return node;
}
}
return null;
That will only find one such node, of course - there may be multiple matches.
You will have to either provide equals method on Point a for state class or just use simple iteration and iterate over both List for comparison. contains method does the same.
If you use any other method it will be time consuming.
Very odd method is use Comparator to check equality
class PointAComparator implements Comparator<State>
{
Point p = null;
public PointAComparator(Point a) {
p = a;
}
#Override
public int compare(State o1, State o2) {
return (p.x == o1.a.x && p.y == o1.a.y) ? 1
: (p.x == o2.a.x && p.y == o2.a.y) ? 1 : -1;
}
}
Above compare method returns 1 for equal else -1 so when you do sorting then each list will have elements at the start which are equal. and then you can check for first element.
i used method overriding on function equals for both the object and achieved my result.
class Point {
int x;
int y;
...
#Override
public boolean equals(Object other){
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof Point))return false;
Point otherPoint = (Point)other;
return (this.x==otherPoint.getX() && this.y==otherPoint.getY() )? true : false;
}
}
public class state implements Comparator<state>{
Point a;
Point b;
private int path_cost=0;
...
#Override
public boolean equals(Object other){
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof state))return false;
state otherState = (state)other;
return ((this.a).equals(otherState.a))? true : false;
}
}

Categories

Resources