如何对LinkedList的浅/深副本执行Junit

问题描述 投票:0回答:1

你好,我做了深层副本,而浅层副本是由用户AndyMan建议的,现在我做了JUnit,我在进行这些测试时遇到了一些小问题:

1。深拷贝方法

   public ListNode<E> deep_clone() {
           first = deep_clone(first);
           ListNode<E> copy = new ListNode<>(first);
     return copy;
    } 

    private static Node deep_clone(Node head) {
        if (head == null) {
            return null;
        }

        Node temp = new Node(head.getData());
        temp.setNext(deep_clone(head.getNext()));

        return temp;
    }

编辑

非常感谢AndyMan提出了这种浅表复制方法:

private static Node shallow_clone(Node head) {
   if (head == null)
      return null;

   Node temp = new Node(head.getData());
   temp.setNext(head.getNext());  // Just copy the reference

return temp;
}

但是有一个问题,如何同时Junit深层复制和浅层复制方法?

我做了以下操作,但Junit测试失败:

@Test
public void test_shallow_clone(){
    ListNode<Integer> list =new ListNode<>();
    for (int i = 0; i < 10; i++)
        list.insert(i);

    ListNode<Integer>cloned =list.shallow_clone();
    //assertSame(cloned,list); //failed i dont know why
    //assertEquals(cloned, list);//Even though its shallow copy i get that they are  not equal!
    assertSame(list.getFirst(), cloned.getFirst());
    assertTrue(cloned.equals(list));
}

以及深层副本的测试:

@Test
public void test_depp_clone(){
    ListNode<Integer> list =new ListNode<>();
    for (int i = 0; i < 10; i++)
        list.insert(i);

    ListNode<Integer>cloned =list.depp_clone();

    assertSame(cloned.getFirst(),list.getFirst());//check for same val..
    //assertEquals(cloned, list);//this make the test fail..
    assertFalse(cloned.equals(list));//okay the are not equal lists this means its deep copy...no implemented equal method :)
}

class ListNode

public class ListNode<E> implements Iterable<E>{

private Node<E> first;
//private Node<E> last;

public ListNode() {
    first = null;
    //last = null;
}

public ListNode(Node head) {
    this.first = head;
    //this.last = this.first;
}

public ListNode(E data) {
    Node head = new Node(data);
    this.first = head;
    //this.last = this.first;
}

@Override
public Iterator<E> iterator() {
    return new LL_Iterator<>(first);
}

private static class Node<E> {

    private E data;
    private Node next;

    public Node() {
        this.data = null;
        this.next = null;
    }

    public Node(E data) {
        this.data = data;
        next = null;
    }

    public Node(E data, Node next) {
        this.data = data;
        this.next = null;
    }

    public E getData() {
        return data;
    }

    public void setData(E val) {
        this.data = val;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }

    @Override
    public String toString() {
        return "Node{" + "data=" + data + ", next=" + next + '}';
    }

}

private static class LL_Iterator<E> implements Iterator<E> {

    private Node<E> curr;//we have to specify the E here because if we dont we have to cast the curr.getData()

    public LL_Iterator(Node head) {
        curr = head;
    }

    @Override
    public boolean hasNext() {
        return curr != null;
    }

    @Override
    public E next() {
        if (hasNext()) {
            E data = curr.getData();
            curr = curr.getNext();
            return data;
        }
        return null;
    }

}

public E getFirst(){
    if(first==null)
        return null;

    return first.getData();
}

public boolean addFirst (E data) {
    if(data==null)
        return false;

    Node t= new Node (data);
    t.setNext(first);
    first=t;
    return true;
}

public E getLast() {
    if (first==null)
        return null;
    return getLast(first).getData();
}

private static<E> Node<E> getLast(Node<E> head) {
    if (head == null) {
        return null;
    }

    Node temp = head;
    if (temp.getNext() != null) {
        temp = getLast(temp.getNext());
    }

    return temp;
}

//insertion....Wie setLast
public boolean insert(E data) {
    if(data==null)
        return false;

    first = insert(first, data);
    //last = getLast();
    return true;
}

private static <E> Node insert(Node head, E data) {
    if (head == null) {
        return new Node(data);
    } else {
        head.setNext(insert(head.getNext(), data));
    }
    return head;
}

public void printList(){
    LL_Iterator it= new LL_Iterator(first);
    printUsingIterator(it,it.next());

}

private static<E> void printUsingIterator (LL_Iterator it, E data){

    //VERDAMMT MAL RHEINFOLGE DER ANWEISUNGEN MACHT UNTERSCHIED
    System.out.print(data+"->");

    if (!it.hasNext()) {
        System.out.print(it.next()+"\n");//THIS WILL PRINT NULL!!!
        return;
    }
    printUsingIterator(it,it.next());
}

public int size() {
    return size(first);
}

private static int size(Node head) {
    if (head == null) {
        return 0;
    } else {
        return 1 + size(head.getNext());
    }
}

public boolean contains(E data) {
    return contains(first, data);
}

public static <E> boolean contains(Node head, E data) {
    if (head == null || data == null) {
        return false;
    }
    if (head.getData().equals(data)) {
        return true;
    }
    return contains(head.getNext(), data);
}

public int countIf(E t) {
    return countIf(first, t);
}

private static <E> int countIf(Node head, E t) {
    if (head == null ||t ==null) {
        return 0;
    }
    if (head.getData().equals(t)) {
        return 1 + countIf(head.getNext(), t);
    }

    return countIf(head.getNext(), t);
}


//TODO: WHY IM GETTING HERE AN OVERRIDE REQUEST FROM THE COMPILER??
//answer because im overriding the damn clone() of the list class which is shallow clone
public ListNode<E> depp_clone() {
    first = depp_clone(first);
    ListNode<E> copy = new ListNode<>(first);
    return copy;
}

private static Node depp_clone(Node head) {
    if (head == null) {
        return null;
    }

    Node temp = new Node(head.getData());
    temp.setNext(depp_clone(head.getNext()));

    return temp;
}

public ListNode shallow_clone (){
    ListNode<E> cloned=new ListNode<>(shallow_clone(first));
    return cloned;
}
private static Node shallow_clone(Node head) {
    if (head == null)
        return null;

    Node temp = new Node(head.getData());
    temp.setNext(head.getNext());  // Just copy the reference

    return temp;
}
java recursion linked-list implementation
1个回答
0
投票
说头指向node0,后者指向node1:头=节点0 =>节点1

在深层副本中,创建两个新节点7和8:deepCopy = node7 => node6

在浅表副本中,创建一个新节点7并将引用复制到原始节点:allowCopy = node7 => node1

private static Node shallow_clone(Node head) { if (head == null) { return null; } Node temp = new Node(head.getData()); temp.setNext(head.getNext()); // Just copy the reference return temp;

}

如果原始node1被更改,它将同时影响原始副本和浅副本。它不会影响深层副本。

现在是术语。已经描述了如何深度复制或浅复制节点。

浅表复制链表实际上没有意义,因为您实际上只是浅表一个节点。当然,您可以复制列表。

如果是数组而不是链接列表,则可以进行浅拷贝或深拷贝。

要测试这些,请覆盖equals()和hashCode()。如果两个列表具有相同的值,我会认为它们相等。为了使两个节点相等,它们应具有相同的值,并且列表的其余部分应相等。如果不重写equals(),则使用Object中的实现。对象使用按位比较需要相同的引用。您可能需要查找一下。

同样,当覆盖equals()时,也需要覆盖hashCode()。这与问题没有直接关系,因此您可能需要照看它。

ListNode equals()和hashCode()

@Override public boolean equals(Object otherObject) { // Objects are equal if they have the same value, and next has the same value if (otherObject instanceof ListNode) { ListNode other = (ListNode)otherObject; return first.equals(other.first); } else { return false; } } @Override public int hashCode() { return first.hashCode(); }

节点equals()和hashCode():

@Override public boolean equals(Object otherObject) { // Objects are equal if they have the same value, && next has the same value if (otherObject instanceof Node) { Node other = (Node)otherObject; return data.equals(other.data) && ((next == null && ((Node) otherObject).getNext() == null) || next.equals(((Node) otherObject).next)); } else { return false; } } @Override public int hashCode() { return data.hashCode(); }
© www.soinside.com 2019 - 2024. All rights reserved.