Java方法等于循环列表

时间:2014-08-06 09:01:25

标签: java list circular-list

以下是我的Element课程的代码:

public class Element<T> {
    Element<T> next;
    Element<T> previous;
    T info;
}

...以及CircularList

public class CircularList<T> {
    Element<T> first=null;

    public void add(Element<T> e){
        if (first==null){
            first=e;
            e.next=e;
            e.previous=e;
        } 
        else { //add to the end;
            first.previous.next=e;
            e.previous = first.previous;
            first.previous=e;
            e.next=first;
        }
    }

    public boolean equals(Object o){
        // TODO
    }
}

我不知道如何为循环列表制作一个equals方法......

只检查是否o instanceof CircularList<T> ?? (if!return false else true?)mmm .. dunno怎么做:(

我知道(从学校开始)我必须检查3个条件:

if this == o return true
if o == null return false
if !o instanceof CircularList<T> return false

...

我现在不知道是否必须检查从list1o的元素,并while ...帮帮我:)

是大学考试,我不能修改或添加方法到元素类..我只需要实现equals类的CircularList<T>方法!

6 个答案:

答案 0 :(得分:3)

我认为关键点是列表是循环。因此,我假设列表

A, B, C, D, E 
   B, C, D, E, A

应被视为相等。因为他们是。当你旋转一个圆圈时,它仍然是一个圆圈。

所以我猜诀窍就是检查另一个列表的每个元素,看看从这个元素开始时列表是否相等。在上面的例子中,人们会测试

  • 列表B, C, D, E, A是否等于A, B, C, D, E?否
  • 列表C, D, E, A, B是否等于A, B, C, D, E?否
  • 列表D, E, A, B, C是否等于A, B, C, D, E?否
  • 列表E, A, B, C, D是否等于A, B, C, D, E?否
  • 列表A, B, C, D, E是否等于A, B, C, D, E?是。最后。

快速实现一些测试用例,我希望涵盖最重要的案例:

public class CircularListEquality {
    public static void main(String[] args) {

        CircularList<String> c0 = createList("A", "B", "C", "D", "E");
        CircularList<String> c1 = createList("A", "B", "C", "D");
        CircularList<String> c2 = createList(     "B", "C", "D", "E");
        CircularList<String> c3 = createList(     "B", "C", "D", "E", "A");

        CircularList<String> c4 = createList("A", "B", "C", "A", "B", "C");
        CircularList<String> c5 = createList("A", "B", "C");

        CircularList<String> c6 = createList("A");
        CircularList<String> c7 = createList("A", "A", "B", "C");

        test(c0, c1, false);
        test(c0, c2, false);
        test(c1, c2, false);
        test(c0, c3, true);
        test(c3, c0, true);
        test(c4, c5, false);
        test(c5, c4, false);
        test(c6, c7, false);
    }

    private static <T> void test(
        CircularList<T> c0, CircularList<T> c1, boolean expected) {
        boolean actual = c0.equals(c1);
        if (actual == expected) {
            System.out.print("PASSED");
        } else {
            System.out.print("FAILED");
        }
        System.out.println(" for " + toString(c0) + " and " + toString(c1));
    }

    private static <T> String toString(CircularList<T> c) {
        StringBuilder sb = new StringBuilder();
        Element<T> current = c.first;
        while (true) {
            sb.append(String.valueOf(current.info));
            current = current.next;
            if (current == c.first) {
                break;
            } else {
                sb.append(", ");
            }
        }
        return sb.toString();
    }

    private static CircularList<String> createList(String... elements) {
        CircularList<String> c = new CircularList<String>();
        for (String e : elements) {
            c.add(createElement(e));
        }
        return c;
    }

    private static <T> Element<T> createElement(T t) {
        Element<T> e = new Element<T>();
        e.info = t;
        return e;
    }
}

class Element<T> {
    Element<T> next;
    Element<T> previous;
    T info;
}

class CircularList<T> {
    Element<T> first = null;

    public void add(Element<T> e) {
        if (first == null) {
            first = e;
            e.next = e;
            e.previous = e;
        } else { // add to the end;
            first.previous.next = e;
            e.previous = first.previous;
            first.previous = e;
            e.next = first;
        }
    }

    public boolean equals(Object object) {
        if (this == object)
        {
            return true;
        }
        if (object == null)
        {
            return false;
        }
        if (!(object instanceof CircularList<?>))
        {
            return false;
        }
        CircularList<?> that = (CircularList<?>) object;

        Element<?> first0 = first;
        Element<?> current0 = first0;
        Element<?> first1 = that.first;
        Element<?> current1 = first1;
        while (true) {
            if (equalSequence(current0, current0, current1, current1)) {
                return true;
            }
            current1 = current1.next;
            if (current1 == first1) {
                return false;
            }
        }
    }

    private static boolean equalSequence(
        Element<?> first0, Element<?> current0,
        Element<?> first1, Element<?> current1) {
        while (true) {
            if (!equalElements(current0, current1)) {
                return false;
            }
            current0 = current0.next;
            current1 = current1.next;
            if (current0 == first0 && current1 == first1) {
                return true;
            }
            if (current0 == first0) {
                return false;
            }
            if (current1 == first1) {
                return false;
            }
        }
    }

    private static boolean equalElements(Element<?> t0, Element<?> t1) {
        if (t0 == null) {
            return t1 == null;
        }
        return equal(t0.info, t1.info);
    }

    private static <T> boolean equal(T t0, T t1) {
        if (t0 == null) {
            return t1 == null;
        }
        return t0.equals(t1);
    }
}

(编辑:增加了另一个测试用例)

答案 1 :(得分:2)

通过稍微调整CircularList课程来获得解决方案:让我们添加length字段。

public class CircularList<T> {
    int length = 0;  // <- this field contains the number of elements that the list has.
    Element<T> first = null;

    public void add(Element<T> e){
        if (first == null){
            first = e;
            e.next = e;
            e.previous = e;
        } 
        else {
            first.previous.next = e;
            e.previous = first.previous;
            first.previous = e;
            e.next = first;
        }

        this.length++;  // <- increment each time you call add().
    }
}

现在,实施equals变得微不足道了:

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;

    @SuppressWarnings("unchecked")
    final CircularList<T> other = (CircularList<T>) obj;

    if(other.length != this.length) {
        return false;
    }

    Element<T> current = this.first;
    Element<T> otherCurrent = other.first;
    int offset = 0;
    boolean found = false;
    do {
        found = checkSequence(current, otherCurrent);
        if(!found) {
            offset++;
            otherCurrent = otherCurrent.next;
        }
    } while(!found && offset < length) ;

    return found;
}

private boolean checkSequence(Element<T> current, Element<T> otherCurrent) {
    int i = 0;
    while(i < length && current.info == otherCurrent.info) {
        current = current.next;
        otherCurrent = otherCurrent.next;
        i++;
    }

    return i == length;
}

我在checkSequence方法中所做的只是迭代每个元素(两个列表中都有length个)并检查它们是否完全相同通过配对。

然后,如果我因i到达length而离开我的循环,则意味着我已经浏览了所有元素并且它们都是相同的。如果此时i小于length,则表示列表的i个元素不相同。

因此,我只返回i == length


除此之外,我还想处理我们正在考虑以下列表的案例:

  • A,B,C
  • C,A,B

...必须是equal

因此,我只需拨打checkSequence,最多length次,将第二个列表与第一个列表进行比较,并列出所有可能的偏移量。

答案 2 :(得分:0)

!运算符只是将true反转为false,反之亦然。

所以,关于那件事的你的代码将意味着与实际的

相反
if !o instanceof CircularList<T>

将返回false,如果 o对象是实例 CircularList<T>。否则,如果o不是CirculatList<T>的实例,则返回true。您只是想反转o instanceof CircularList<T>的实际结果。

答案 3 :(得分:0)

这等于实现怎么样?我们可以避免调整你的课程。

    public boolean equals(CircularList<T> other)
        {
           **Standard checks will go here (ref equals, class type etc)**

            boolean result = false;
            result = first.equals(other.first);

            Element<T> next = first.next;
            Element<T> nextOfOther = other.first.next;

            while (null != next && null != nextOfOther)
            {
                // break cyclic loop
                if (next.equals(first))
                    break;

                result = next.equals(nextOfOther);

                if (!result)
                    // We know they aren't equal so break
                    break;

                next = next.next;
                nextOfOther = nextOfOther.next;

            }

            return result;
        }

答案 4 :(得分:0)

指令:this == o;只有当它们具有相同的地址时(当它是同一个对象时)才返回true,我认为当两个列表包含相同的元素时,你需要的东西会返回true,试试这个:

public boolean equals(CircularList<T> other){
    Element<T> e1 = first;
    Element<T> e2 = other.first;
    while(e1.next != first && e2.next != other.first){
       if(e1.info == e2.info){
           e1 = e1.next;
           e2 = e2.next;
       }
       else return false;
    } 
    if (e1.next == first && e2.next == other.first)
         return true;
    else return false;

}

我认为这会起作用!!

答案 5 :(得分:0)

这个怎么样,在这里我将首先找到并检查长度,然后检查元素。

public boolean equals(CircularList<T> other)
    {
        boolean result = false;
        result = first.equals(other.first);

        if (!result)
            return result;

        Element<T> next = first.next;
        Element<T> nextOfOther = other.first.next;

        int firstCount = 1;

        while (null != next)
        {
            if (next.equals(first))
                break;

            firstCount++;
            next = next.next;
        }

        int secondCount = 1;

        while (null != nextOfOther)
        {
            if (nextOfOther.equals(other.first))
                break;

            secondCount++;
            nextOfOther = nextOfOther.next;
        }

        if (firstCount != secondCount)
        {
            result = false;
        }

        next = first.next;
        nextOfOther = other.first.next;

        while (firstCount > 1)
        {
            result = next.equals(nextOfOther);
            if (!result)
                // We know they aren't equal so break
                break;

            next = next.next;
            nextOfOther = nextOfOther.next;
            firstCount--;

        }

        return result;
    }