Java - 双向链表深复制构造函数

问题描述

作为我任务的一部分,我们被要求创建一个构造函数,该构造函数将对另一个列表进行深度复制。 以下是我们对它的描述。

复制构造函数:实现一个接受 DSList 对象的复制构造函数。复制构造函数应该执行传递给构造函数的 DSList 的深层复制:新的 DSList 不应包含对第二个 DSList 中的 Node 对象的引用。 (两个 DSList 应该是独立的:更改一个 DSList 中 Node 对象的内容不应影响另一个)。

你们能帮我复制构造函数吗?我不知道怎么写。

非常感谢您提供的任何见解。谢谢。

下面是 DSList 类的第一部分。

public class DSList implements List {
    public Node head;

    /**
     * This is a constructor of the DSList class. 
     * The constructor takes no parameters.
     */
    public DSList() {       
    }

    /**
     * This is a constructor of the DSList class. 
     * The constructor takes in one parameter and 
     * set this to the given node. 
     * @param head_ is the given node.
     */
    public DSList(Node head_) {     
        this.head = head_;
    }

    /**
     * This is the copy constructor. The constructor takes in another DSList object and copy it to
     * a new DSList. Each copy created is independent of the original DSList.
     * @param other is another DSList object.
     */
    public DSList(DSList other) { // copy constructor. 
        // this needs to be filled///
    }

除此之外,我们还提供了单独的 Node 类和 Token 类(如下所示)。

public class Node {
    public Node next;
    public Node prev;
    private Token t;

    public Node(Node next,Node prev,Token token) {
        this.next = next;
        this.prev = prev;
        this.t = token;
    }

    public Token getToken() {
        return t;
    }

    @Override
    public boolean equals(Object other) {
        if (this == other)
            return true;
        if (other == null)
            return false;
        if (!(other instanceof Node))
            return false;

        return t.equals(((Node)other).getToken());
    }

    @Override
    public int hashCode() {
        if ( t == null )
            return 0;
        return t.hashCode();
    }
}

public class Token {
    public enum Type { OPERATOR,OPERAND,PAREN };
    public Type type;
    
    private String operator;
    private double operand;

    public Token(double result) {
        this.operand = result;
        this.type = Type.OPERAND;
    }
    
    public Token(String op) {
        this.operator = op;
        this.type = Type.OPERATOR;
        
        if ( this.operator.equals("(") || this.operator.equals(")") ) {
            this.type = Type.PAREN;
        }
    }
    
    public Token(Token other) {
        this.operator = other.operator;
        this.operand = other.operand;
        this.type = other.type;
    }
    
    public String getoperator() {
        return operator;
    }

    public double getoperand() {
        return operand;
    }

    public int getPrecedence() {
        if ( type == Type.PAREN )
            return -1;
        if ( type != Type.OPERATOR )
            return 0;
        
        switch ( operator ) {
        case "+":
        case "-":
            return 0;
        case "*":
        case "/":
            return 2;
        }
        return 0;
    }
    
    @Override
    public boolean equals(Object obj) {
        if ( obj == null )
            return false;
        if ( obj == this )
            return false;
        if ( !obj.getClass().equals(Token.class)) 
            return false;
        
        Token t = (Token)obj;
        if ( t.type == this.type ) {
            if ( this.type == Type.OPERATOR )
                return operator.equals(t.operator);
            else
                return operand == t.operand;
        }
        return false;
    }
    
    @Override
    public int hashCode() {
        return 0;
    }
    
    public String toString() {
        return this.type == Type.OPERAND ? "" + this.operand : this.operator;
    }
}

解决方法

带有签名 public Token(Token other) 的构造函数是复制构造函数的一个很好的例子。调用构造函数,然后将其他 Token 的成员设置为与新 Token 的成员相同。

您有一个由许多链接在一起的节点组成的 DSList。如果要复制所有这些节点,则必须创建一个新的空 DSList。此 DSList 将包含原始 DSList 中节点的所有副本。接下来,您需要遍历原始 DSList 中的所有节点,通过在每个节点上调用复制构造函数来复制节点,然后将这些节点插入到新的 DSList 中。这意味着您将在 Token 和 Node 上调用复制构造函数,因为 DSList 包含对 Node 的引用,而 Node 包含对 Token 的引用。完成此过程后,新的 DSList 将是原始 DSList 的深拷贝版本。

代码最终看起来像这样。

public DSList(DSList original)
{
    DSList newListCopy = new DSList();
    if (this.head != null)
    {
        // Call the copy constructor for the head node and save the head for the new list.
        newListCopy.head = new Node(this.head);
        // Temporary variables for inserting and iterating lists.
        Node newLinkedNode = newListCopy.head;
        Node iterator = this.head.next;
        // Looping through the lists.
        while (iterator != null)
        {
            // Insert the copy of the node from the other list.
            Node prev = newLinkedNode;
            newLinkedNode.next = new Node(iterator);
            newLinkedNode = newLinkedNode.next;
            newLinkedNode.prev = prev;
            iterator = iterator.next;
        }
    }
    return newListCopy;
}

一个关键的见解是,如果您有对象,则必须通过使用 new 创建该对象的新实例来复制它们。对于属于您要复制的对象的一部分的所有对象,您都需要像 token 中的复制构造函数。