我是一名C ++初学者,试图编写一个函数来在C ++中创建链表的深层副本。该函数调用自身,直到它位于源列表中的最后一个节点,然后复制该节点。但是,当我运行此操作时,我收到分段错误或EXC_BAD_ACCESS错误。以下是我到目前为止的情况:
struct node {
int data;
node* next;
};
void copy_list(const node*& source_ptr, node*& dest_ptr)
{
if (dest_ptr != nullptr){
clear_list(dest_ptr);
}
if (source_ptr == nullptr) return; //we already cleared dest_ptr
if (source_ptr->next == nullptr) // this is the last node
{
dest_ptr = new node(); //initialize in memory
dest_ptr->data = source_ptr->data; //copy the last datum
dest_ptr->next = nullptr; //since this is the end
return;
}
const node* cursor = source_ptr->next; // this happens if source is not yet at the end
copy_list(cursor, dest_ptr->next);
}
我知道还有其他类似的问题,但是他们对我没有帮助。我也尝试过使用除递归之外的其他方法,例如while循环看起来像:
dest_ptr = new node();
dest_ptr->data = source_ptr->data;
node* dest = dest_ptr->next;
const node* cursor = source_ptr->next;
while(cursor != nullptr)
{
dest = new() node;
dest-> data = cursor->data;
//dest->next = nullptr;
dest = dest->next;
cursor = cursor->next;
}
while循环不会出错,但副本为空(除了在while循环外复制的第一个节点)。
非常感谢任何帮助。谢谢!
答案 0 :(得分:2)
如果您是初学者,请从简单的事情开始:在理解循环之前尽量避免递归。所以我只会对循环版本发表评论(无论如何,递归对这个特定问题来说是一种糟糕的方法)。
如果代码没有做你想做的事情,你应该尝试在调试器中单步执行它以记录它究竟是做什么,或者尝试将其解释为某人的指令列表(rubber duck这是理想的,因为它的病人)。
你也可以通过推理代码来解决这个问题:
每个变量都应有明确定义的目的,最好反映在其名称中。我可以看到source_ptr
的目的是指向源列表。 cursor
的目的是遍历源列表。
dest_ptr
可能用于保存新创建的副本。您可以通过将第一个data
复制到其中来开始。
然而,dest
的目的是什么?首先,将dest_ptr->next
(实际上为空)的值复制到其中。然后,在循环中,您立即用新创建的节点覆盖dest
。将cursor->data
复制到此新节点,并将(此时未初始化)指针dest->next
复制到dest
。但请注意,您从未读过dest
的值,只是在下一次迭代中覆盖它。
我怀疑你确实希望dest
成为指向node
指针的指针,你打算这样做:
dest_ptr = new node();
dest_ptr->data = source_ptr->data;
node **dest = &dest_ptr->next;
const node *cursor = source->ptr->next;
while (cursor)
{
*dest = new node();
(*dest)->data = cursor->data;
dest = &((*dest)->next);
cursor = cursor->next;
}
这可以做你想要的,但指针的指针是丑陋的。最好使用dest
作为遍历目标列表的第二个游标:
dest_ptr = new node();
dest_ptr->data = source_ptr->data;
node *dest = dest_ptr;
const node *cursor = source_ptr->next;
while (cursor)
{
dest->next = new node();
dest = dest->next;
dest->data = cursor->data;
cursor = cursor->next;
}