C ++以递归方式深度复制链表

时间:2014-09-19 15:15:55

标签: c++ recursion linked-list

我是一名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循环外复制的第一个节点)。

非常感谢任何帮助。谢谢!

1 个答案:

答案 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;
}