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;
}
我想我在这里创建了一个循环链表。所以我所做的是覆盖equals方法以确保处理循环引用:
由于某种原因,LinkedList.equals似乎没有返回...是因为我的循环链表,还是我错过了一些条件?
答案 0 :(得分:2)
此代码的主要问题是您的比较不会在循环引用时终止,并且如果所有内容字段相等则将永远循环。它将一直持续到下一个比较,因为下一个项目总是在那里(因为它是一个圆圈),这将永远持续下去。
myUtil.equals(this.contents, item.contents) && myUtil.equals(this.next, item.next);
要解决此问题,最简单的方法是向每个List项添加一个布尔私有'visited'字段。比较时,在比较后设置每个项目的访问量。如果两者都未访问且相同,则继续。如果只访问过一个,则列表不相同。如果两者都被访问过,那么您已经比较了可访问的整个列表。通常,在列表中包含循环是一个坏主意,并且存在专门用于检测它们的算法。这可能是一个令人困惑的话题。这是一个coverage循环检测,可以帮助您进一步了解问题。请记住,如果您使用被访问字段,则必须使用equals()中的另一个循环取消所有这些循环,以允许它再次运行。
另一方面,您没有初始化列表节点的内容字段以进行测试。这没关系,因为它们被初始化为null,但通常最好显式初始化所有字段。
一般来说,您也不需要equals(Object item)
覆盖。尝试
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;
}
这回溯并取消了一些基本的递归。我显然没有编译这个,但这是它的主旨,我想(我希望没有太多的错误)
答案 1 :(得分:1)
两个问题,首先你没有循环链表。以下代码创建了2个列表,list1.next = list2,list2.next = null。没有创建圆圈。
LinkedList myList = new LinkedList();
myList.next = new LinkedList();
LinkedList head = myList.next;
myList.next = head;
其次,如果DID有一个循环链表,下面会产生无限循环,因为没有达到最终条件,这是因为在循环链接链接中,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);
}
为了有效地执行此操作,您需要提供一些机制来以非循环方式迭代列表,即使此机制是私有的并且不向其他用户公开。一种方法是将单个节点标记为“根”。
答案 2 :(得分:0)
return myUtil.equals(this.contents, item.contents)
&& myUtil.equals(this.next, item.next);
我认为这是你怀疑的问题,当你执行&&的第二个表达时即myUtil.equals(this.next, item.next);
您输入执行此行的myUtil.equals方法:
return (x == y) || (x != null && x.equals(y));
反过来使用x
的.equals()方法,它将重复其item.next
的过程,依此类推,因为你有一个循环链接列表。
答案 3 :(得分:0)
这将导致无限循环,这是因为在代码中:
public static boolean equals(Object x, Object y) {
return (x == y) || (x != null && x.equals(y));
}
x.equals(y)
将再次调用:
public boolean equals(LinkedList item) {
return myUtil.equals(this.contents, item.contents)
&& myUtil.equals(this.next, item.next);
}
但如果您正在执行myList1.equals(myList1)
,则不会得到无限循环,因为(x==y)
中的myUtils.equals()
将返回true
,因此如果您进行比较,则不会发生无限循环相同的对象。
但是,当您比较不同的对象时,您将进入无限循环。
这不是循环列表问题,这是因为您选择的代码设计。
答案 4 :(得分:0)
最后完成了我的等于方法的实现。为此,我必须自己使用其他检查工具。我不能说它是有效的,但是检查了一些异常状态。
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;
}
和等于方法:
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 方法返回旋转操作的计数,并在0到 size-1 之间变化。我希望它会有用。