-3

I am a C++ beginner trying to write a function to create a deep copy of a linked list in C++. The function calls itself until it is at the last node in the source list, then copies that node. However when I run this I get a segmentation fault or EXC_BAD_ACCESS error. Here is what I have so far:

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);
}

I know there are other questions similar to this, but they haven't helped me. I have also tried using other methods than recursion for example a while loop that looks something like:

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

The while loop doesn't give errors but the copy is blank (except for the first node which is copied outside the while loop).

Any help is greatly appreciated. Thanks!

  • 1
    The problem with your `while`-loop (that should be preferred over recursion) is that the line `dest = dest->next;` overwrites the node again. – 5gon12eder Sep 19 '14 at 15:20
  • Thanks for the comment, I can see your point. So how to fix that? Do I need another variable? But I somehow have to use an indexing variable for the while loop to work, right? –  Sep 19 '14 at 15:49

1 Answers1

1

If you're a beginner, start from simple things: try to avoid recursion until you understand loops. So I will only comment on the loop version (recursion is a bad approach to this particular problem anyway).

If code doesn't do what you want, you should try stepping through it in a debugger to note what exactly it does, or try to explain it as a list of instructions to someone (a rubber duck is ideal for this, as it's patient).

You can also approach this by reasoning about the code:

Each variable should have a clearly defined purpose, ideally reflected in its name. I can see that the purpose of source_ptr is to point to the source list. And the purpose of cursor is to traverse the source list.

dest_ptr is probably intended to hold the newly created copy. You're taking a good start by copying the first data into it.

What is the purpose of dest, however? You start by copy the value of dest_ptr->next (which will actually be null) into it. Then, in the loop, you immediately overwrite dest with a newly created node. Copy cursor->data into this new node, and copy the (uninitialised this time) pointer dest->next into dest. However, note that you never read the value of dest, you just overwrite it in the next iteration.

I suspect you actually intended dest to be a pointer to a pointer to node, and your intention was to do this:

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

This would do what you want, but pointers to pointers are ugly. It would be better to use dest as a second cursor for traversing the destination list:

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;
}
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • Thanks for the clear and helpful answer. I did indeed intend for dest to be a second cursor; it appears that the problem was **when** I was updating it! –  Sep 19 '14 at 15:52
  • @Kiochi Either stepping in a debugger or explaining the code would probably have shown you. Learn to use these two techniques, they're a basic tool in any programmer's toolbox. – Angew is no longer proud of SO Sep 19 '14 at 15:55
  • 1
    @Kiochi In case you're interested, there's also a [list of good C++ books](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) maintained here on SO. – Angew is no longer proud of SO Sep 19 '14 at 16:11
  • And one tip for asking future questions: step your code through a debugger first, and summarise in the question what you've learned from this (assuming it doesn't solve your issue straight away). Your attitude is great, but unfortunately you're rather an exception; in general, SO suffers from a constant flood of "here's my 400 lines of codez, debugg it for meh!" questions, so people here generally want to see evidence of effort put in by the asker. – Angew is no longer proud of SO Sep 19 '14 at 16:17