对如何制作双链表的深度副本感到困惑?

Confused on how to do a deep copy of a doubly Linked List?

本文关键字:副本 深度 何制作 链表      更新时间:2023-10-16

我一直在尝试实现双链表的深层副本,但一直遇到麻烦。我必须多次做不同的事情,但我最终得到了一个地址错误。我只需要一个解释如何正确做到这一点。

列表.H

class List 
{
public:
List();
~List();
List(const List& c);
List& operator= (const List& t);
private:
List *Next;
List *Prev;
Node *Head;

列表.cpp

List::~List()
{
Node* move = Head;
while (move!=NULL)
{
Node *temp = move->Next;
delete move;
move = temp;
}
}
List::List(const List& c)
{
name = c.name;
if (c.Head == NULL) {
Head = NULL;
}
else {
Head = new Node(*c.Head);
Node* Current = Head;
Node* ObjHead = c.Head;
Node* CurrentObj = ObjHead;
while (Current->Next!=NULL) {
Current->Next = new Node (CurrentObj->Next->condiments);
}
}
}

复制链表涉及三件事:

  1. 遍历正在复制的列表。
  2. 从原始节点复制新节点。
  3. 对于 (2( 中的每个新节点,将其尾部链接到链表。

其中第一个是微不足道的,第二个是相当基本的,但第三个是经常把人扔到循环的那个。对于您的复制 ctor,一种方法是使用指针到指针。这允许我们通过自己的地址对链表中的每个指针进行寻址。

List::List(const List& c)
: Head(nullptr)
, name(c.name)
{
Node *prev = nullptr;
Node **pp = &Head;
for (const Node *p = c.Head; p; p = p->Next)
{
// make a new node, storing its address at the
// pointer obtained by dereference of `pp`. the
// first iteration that will be the Head member.
*pp = new Node(*p);
(*pp)->Prev = prev;
prev = *pp;
// now just advance `pp` to point to the `Next`
// member of the node we just hung on the list.
pp = &(*pp)->Next; 
}
*pp = nullptr; // terminate the list.
}

这假设您Node类支持复制构造(它有更好的(。 但仅此而已。由此,您可以使用 copy/swap 习惯用法来制造复制赋值运算符,并拥有一个基本的三条规则合规性列表类。

你可以使用假人头开始。深度复制完成后,您可以将head设置为下一个假人头并删除假人头。您也不必以这种方式检查if (c.Head == NULL)

Node *ptr1, *ptr2;
head = ptr1 = new Node();
ptr2 = c.head;
while (ptr2)
{
ptr1->next = new Node(*ptr2);
ptr1 = ptr1->next;
ptr2 = ptr2->next;
}
Node *temp = head;
head = head->next;
delete temp;