slash89mf slash89mf - 19 days ago 5
C++ Question

Insert in list at second position c++

I would like to insert an element inside a list, as second element, creating a new list without modifying original one.

Example:
list 1 2 3 4 5, cin>> 55, then new list become 1 55 2 3 4 5.

Problem is that both lists are modified. Why is this happening?

ptr_list insertAfterFirstElem(ptr_list head){
ptr_list tmp;
tmp=new list;
cout<<"Insert value"<<endl;
cin>>tmp->val;
tmp->next=head->next;
head->next=tmp;
return (head);

}


I wrote a insertAtTop function that works fine:

ptr_list insertAtTop(ptr_list head){
ptr_list tmp;
tmp=head;
head=new list;
cout<<"Insert value"<<endl;
cin>>head->val;
head->next=tmp;
return (head);

}


Can you explain what is the difference between these two functions? Why insertAtTop() does not modify the original list?

Answer

Both lists share the same cells; that's why you have trouble.

head: xxx -> yyy -> zzz -> ttt
       ^
res: --|

If tmp = uuu, you are inserting it at second position,

head: xxx -> uuu-> yyy -> zzz -> ttt
       ^      ^
res: --|      |-- tmp

But, as you can see, the original list starting from head is also modified.

If you don't want to modify it you need to duplicate the original list before the insertion:

head: xxx -> yyy -> zzz -> ttt
copy: xxx -> yyy -> zzz -> ttt
       ^
res: --|

then you can insert

head: xxx -> uuu-> yyy -> zzz -> ttt
copy: xxx -> uuu-> yyy -> zzz -> ttt
       ^      ^
res: --|      |-- tmp

A possible solution could be:

ptr_list copyList(ptr_list head) {
    ptr_list copy = nullptr;
    ptr_list* copy_last = &copy;
    for (ptr_list iter = head; iter != nullptr; iter = iter->next) {
      *copy_last = new list(*iter);
      copy_last->val = iter->val;
      copy_last->next = nullptr;
      copy_last = &copy_last->next;
    };
    return copy;
}

ptr_list insertAfterFirstElem(ptr_list head){
    ptr_list copy = copyList(head);
    ptr_list tmp;
    tmp=new list;
    cout<<"Insert value"<<endl;
    cin>>tmp->val;
    tmp->next=copy->next;
    copy->next=tmp;
    return (copy);
}

Now with insertAtTop(ptr_list head) you still have problems of sharing but you don't see it immediately. It creates

    head: xxx -> uuu-> yyy -> zzz -> ttt
           ^
res: uuu --|

So if after some time, you want to insert another cell in second position from head you will also modify your result.

An implementation without any shares of insertAtTop is

ptr_list insertAtTop(ptr_list head){
    head = copyList(head);
    ptr_list tmp;
    ...
}

Also don't forget to free the cells. Freeing with shares is almost impossible if you don't use additional mechanism like reference-counting.