【问题标题】:How to Deep Clone Doubly Linked List?如何深度克隆双向链表?
【发布时间】:2023-04-03 23:06:01
【问题描述】:

我需要编写一个程序(实现双向链表):

  • 打印出列表中从列表前面到列表末尾的项目列表(这是我的toArrayFromFirst() 方法)
  • 打印出列表中从末尾到列表前面的项目列表(倒序)(这是​​我的toArrayFromLast() 方法)
  • DeepClones 列表(这是我的deepClone() 方法)
  • 从列表的前面到列表的末尾打印出列表副本中的项目列表。

我的问题:

  • 我认为我的 deepClone() 方法中混合了单链表和双链表的代码。
  • 我的程序输出不正确,我不确定是因为我将元素错误地插入到列表中,或者我的列表显示不正确,或者两者兼而有之。
  • 我收到此错误:“线程“main”中的异常 java.lang.CloneNotSupportedException: DLL.DLL”(错误出现在这行代码中:DLL<E> other = (DLL<E>)super.clone();(在我的 deepClone() 方法中)李>

这是我的代码当前输出的内容:

从第一个到最后一个列表:比利时 德国

从最后到第一名:英国德国法国比利时

(然后当我尝试深度克隆列表时出现错误)

这就是我希望我的代码输出的内容:

从头到尾依次为:比利时法国美国德国英国

从最后到第一名:英国德国美国法国比利时

深度克隆列表:比利时法国美国德国英国

这是我的 DoubleLinkedList 类:

package DLL;

public class DLL<E>
{
    private Node header = null;                         //header sentinel
    private Node trailer = null;                        //trailer sentinel
    private int size = 0;                               //number of elements in list

//nested Node class
private static class Node<E>
{   
    private E element;                              //reference to element stored at this node
    private Node prev;                              //reference to previous node in list
    private Node next;                              //reference to subsequent node in list

    public Node(E e)
    {
        element = e;
    }
    public E getElement()
    {
        return element;
    }       
    public Node<E> getPrev()
    {
        return prev;
    }
    public Node<E> getNext()
    {
        return next;
    }
    public void setPrev(Node<E> p)
    {
        prev = p;
    }
    public void setNext(Node<E> n)
    {
        next = n;
    }
    public void displayNode()
    {
        System.out.println(element + " "); 
    }
}

//returns number of elements in linked list
public int size()
{
    return size;
}

//tests whether linked list is empty
public boolean isEmpty()
{
    return header == null;
}

//adds element e to front of list
public void addFirst(E e)
{
    Node newNode = new Node(e);

    if (isEmpty())
    {
        trailer = newNode;
    }
    else
    {
        size++;
        header.prev = newNode;
        newNode.next = header;
    }
    header = newNode;
}

//adds element e to end of list
public void addLast(E e)
{
    Node newNode = new Node(e);

    if (isEmpty())
    {
        header = newNode;
    }
    else
    {
        size++;
        trailer.next = newNode;
        newNode.prev = trailer;
    }
    trailer = newNode;
}

//removes and returns first element of list
public Node removeFirst()
{
    Node temp = header;

    if (header.next == null)
    {
        trailer = null;
    }
    else
    {
        size--;
        header.next.prev = null;                    //null <-- old next
    }
    header = header.next;
    return temp;
}

//removes and returns last element of list
public Node removeLast()
{
    Node temp = trailer;

    if (header.next == null)
    {
        header = null;
    }
    else
    {
        size--;
        trailer.prev.next = null;                   //old prev --> null
    }
    trailer = trailer.prev;
    return temp;
}

//displays array of strings with elements in order from head to tail
    public void toArrayFromFirst()
    {
        System.out.println("List from first to last: ");
        Node current = header;

        while (current != null)
        {
            current.displayNode();
            current = current.next;
        }
        System.out.println("");
    }

    //displays array of strings with elements in order from tail to head
    public void toArrayFromLast()
    {
        System.out.println("List from last to first: ");
        Node current = trailer;

        while (current != null)
        {
            current.displayNode();
            current = current.prev;
        }
        System.out.println("");
    }

    //displays cloned array with elements in order from head to tail
            public void clonedToArrayFromFirst()
            {
                System.out.println("Deep cloned list: ");
                Node current = header;

                while (current != null)
                {
                    current.displayNode();
                    current = current.next;
                }
                System.out.println("");
            }

    //returns copy of list (deep clone)
    public DLL<E> deepClone() throws CloneNotSupportedException
    {
        DLL other = new DLL<E>();

        if (size > 0)
        {
            other.header = new Node<>(header.getElement());
            Node<E> walk = header.getNext();
            Node<E> otherTrailer = other.header;

            while (walk != null)
            {
                Node<E> newest = new Node<>(walk.getElement());
                otherTrailer.setNext(newest);
                otherTrailer = newest;
                walk = walk.getNext();
            }
        }
        return other;
    }

}

这是我的 main():

package DLL;

public class DLLTest 
{

    public static void main(String[] args) throws CloneNotSupportedException 
    {
        DLL myList = new DLL();
        DLL clonedList = new DLL();

        myList.addFirst("USA");
        myList.addLast("Germany");
        myList.addFirst("France");
        myList.addLast("England");
        myList.addFirst("Belgium");

        myList.toArrayFromFirst();
        myList.toArrayFromLast();

        clonedList = myList.deepClone();
        clonedList.clonedToArrayFromFirst();
    }
}

【问题讨论】:

  • 你试过什么?您是否尝试在互联网上搜索错误消息?
  • @MiserableVariable,我没有专门在网上搜索过错误信息。然而,我查看了几个深度克隆和输出双向链表的示例,但我仍然不确定我的代码有什么问题。
  • 您的 addFirst() 方法有问题。您没有在其中设置标题。这应该可以解决您的问题,或者大部分问题。
  • 为什么要将第二个参数传递给Node,因为它始终为空,而且您甚至没有在构造函数中使用它?
  • @Bifz - 我实际上不确定我为什么这样做。我一直在看很多例子,所以我确信其中一个有两个参数传递到 Node 中,然后我可能在每次调用该方法时传入 null 只是为了使参数匹配。 (我在编程方面很糟糕)但是,即使我在所有情况下都删除了第二个参数,我仍然有我在下面的评论中列出的相同的空指针异常(作为对 Jason 的回应)

标签: java list output clone


【解决方案1】:

您在循环中多次同时使用这两行代码:

current = current.getNext();
current = current.next;

除此之外,您不会在任何地方更新 DLL 大小。所以你的deepClone 甚至没有输入你的条件if (size &gt; 0)

最后,不要使用super.clone(),只需创建一个新的 DLL 并添加您的值。

【讨论】:

  • 非常感谢!!我将代码完全按照您的建议进行了编辑,并且效果很好。
【解决方案2】:

我在addFirst() 中发现了一个问题。您应该始终设置标题:

//adds element e to front of list
public void addFirst(E e)
{
    Node newNode = new Node(e, null);

    if (isEmpty())
    {
        trailer = newNode;
    }
    else
    {
        header.prev = newNode;
        newNode.next = header;
    }
    header = newNode;
}

【讨论】:

  • 感谢您的关注。这是我一个粗心的错误。我已根据您的建议更新了代码。现在我的代码行中出现空指针异常:private Node next; in my private static class Node
猜你喜欢
  • 2017-05-16
  • 1970-01-01
  • 1970-01-01
  • 2012-03-30
  • 1970-01-01
  • 1970-01-01
  • 2019-03-25
  • 2017-09-17
  • 2017-09-01
相关资源
最近更新 更多