考虑到这是我的函数:
void addtoSameList(const List &another){
for (Node *temp = new Node(*head); temp != nullptr; temp = temp -> next){
Node *ptr = other.head;
Node *temp2 = new Node;
temp2->value = temp->value;
while (ptr -> next != nullptr) {
ptr = ptr -> next;
}
ptr->next = temp2;
temp2->next = nullptr;
}
return;
}
我的目标是将链接列表附加到自身,我不知道到底出了什么问题。 例如,如果我在主函数中有一个名为 n 的链接列表,然后我声明:
n.addtoSameList(n);
这意味着 &other 将指向与 n 相同的节点,我想我会创建一个新节点并深度复制 n 的内容。
但是,我的两个输出要么是我最终进入无限循环,要么是某个节点最终被跳过。
如何解决此问题?
此代码存在许多问题。首先,该接口并不建议唯一的用途是将链表附加到自身。它也不表明在任何其他情况下都需要深拷贝。
所以,让我们调整一下要求...
您需要一个成员函数,该函数会将链表的副本追加到现有链表。那么自追加的情况自然就从问题描述中消失了。
这里的方法是逐步浏览传入的链表,仔细复制每个节点,然后重新调整主链表上的指针,以指向新节点和新节点中的指针,以设置为显示为列表的末尾。这将在单步执行列表时保持列表不变。
不过这里有一个陷阱。如果你是自追加的,你就有可能创建一个无限循环。因此,在开始此过程之前,您应该找到传入列表的结束节点,并始终使用它来确定是否已到达列表的末尾。如果您维护尾部指针,这是微不足道的。如果不这样做,则意味着列表遍历。
另一种方法是简单地先创建一个副本,小心地维护指向副本第一个节点的指针。然后,只需调整尾部节点的下一个指针以指向新列表,然后将尾部节点(如果您在 LinkedList 数据结构中维护该指针(调整为指向副本的尾部节点。这可能就是你应该走的路。它更清洁、更高效。主要缺点是在执行异常处理时进行清理。但是,在你的水平上,你现在不应该关心这一点。
这是一种替代方法。创建三个指针:ptrBegin
、ptrEnd
和ptrNew
。ptrBegin
指向链表的开头并遍历链表,以便ptrEnd
和ptrNew
指向链表的最后一个元素。然后递增ptrBegin
,直到ptrBegin != ptrEnd
同时将ptrBegin
处的数据复制到ptrNew->next
处的新节点,并递增ptrNew
。