【问题标题】:C++ Deep Copying Linked ListC++ 深度复制链表
【发布时间】:2017-04-09 11:08:56
【问题描述】:

首先,这是我目前正在尝试解决的一项任务的一部分。我正在尝试创建一个复制构造函数来深度复制给定的 LinkedList。 我已经编写了 LinkedList 方法。

这是 LinkedList.h 文件的必要部分。

LinkedList.h
private:
    struct node {
        Val data;
        node* next = nullptr;

    };

    typedef struct node* nodePtr;


    nodePtr head = nullptr;
    nodePtr current = nullptr;
    nodePtr temp = nullptr;
};

给定参数:“LinkedList::LinkedList(const LinkedList & ll)” ll 是要复制的链表。 我首先测试了链表中是否有头部,如果没有,则表示链表为空。 然后我将头部从旧列表复制到新列表中。 然后我将新的电流设置到头部,为 while 循环做准备。 在 while 循环中,我正在复制当前节点的数据以及指向下一个节点的指针。 最后,我将 next 指针设置为 nullptr 以表示新列表的结束。

LinkedList.cpp

LinkedList::LinkedList(const LinkedList & ll){
    if (ll.head == nullptr) {
        return;
    }
    head = ll.head;
    current = head;


    while (ll.current->next != nullptr) {
        current->data = ll.current->data;
        current->next = ll.current->next;
    }
    current->next = nullptr;
}

我不确定这是否是深度复制。 我也知道 ll.current 的起始位置不在头部。 我试过 ll.current = ll.head。但是,既然给定这个函数是 const 的。我不能这样设置。

还给出了另一个函数: LinkedList & LinkedList::operator=(const LinkedList & ll) { } 我怀疑可能需要。我希望我可以选择使用它。

【问题讨论】:

  • 先写复制构造函数和析构函数。一旦你实现了这些函数,赋值运算符就很简单了。此外,如果ll.headnullptr,您的复制构造函数会立即出错。原因是你没有初始化任何成员——你只是return
  • 这不是深度复制。深度复制涉及在将值复制到成员之前为其分配内存。
  • 另外,您当前正在覆盖 current->datacurrent->next 中的值,而不更改 current 指向的位置。

标签: c++ struct linked-list


【解决方案1】:

您需要在添加新内存或新列表元素时分配它们,更改您的代码以执行以下操作:

// LinkedList.cpp

LinkedList::LinkedList(const LinkedList & ll)
{
    if (ll.head == nullptr)
        return;

    // Create a temp variable since ll.current doesn't move/change.
    node* tmp = ll.head;

    // Allocate a new node in memory.
    head = new node;
    // Copy over the value.
    head->data = tmp->data;
    // Set the 'next' value to null (the loop will fill this in). 
    head->next = nullptr;
    // Point 'current' to 'head'.
    current = head;
    
    // Move to next item in ll's list.
    tmp = tmp->next;

    while (tmp != nullptr)
    {
        // Allocate new memory for a new 'node'.
        current->next = new node;
        // Point to this new 'node'.
        current = current->next;
        // Copy over the data.
        current->data = tmp->data;
        // By default set the 'next' to null.
        current->next = nullptr;
        // Move along ll's list.
        tmp = tmp->next;
    }
}

另外,在你的课堂上摆脱typedef node* nodePtr。没有必要,只需将node* 用于headcurrenttemp 会更简洁。最后,不要忘记在你的类的析构函数中清除动态分配的内存:

LinkedList::~LinkedList()
{
    current = head;

    while(current != nullptr)
    {
        current = current->next;
        delete head;
        head = current;
    }
}

【讨论】:

  • 你看我的评论了吗?如果ll.headnullptr,则由于成员变量未初始化,复制构造函数立即出错。您应该首先在成员初始化列表中初始化所有指针。 LinkedList::LinkedList(const LinkedList & ll) : head(nullptr), current(nullptr) {...}
  • ll.head 是否为空会被检查。在.h 文件中,他已经将headcurrenttemp 设置为nullptr,用于初始化它们。我错过了什么吗?在 C++11 中,您可以按照 OP 编写的方式在头文件中进行初始化。
【解决方案2】:

这是行不通的,因为您永远不会为实际的列表对象分配新的列表元素(使用“new”运算符),而只会重用现有的。想想会发生什么,如果 ll 的元素比实际列表多?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-26
    • 2015-02-28
    • 1970-01-01
    • 1970-01-01
    • 2011-12-02
    • 2020-11-08
    • 2021-12-12
    相关资源
    最近更新 更多