Not understanding code snippet that reverses linked list using recursion in C

163 views Asked by At
void reverse(LIST **head)
{
    if(!*head)
      return ;

    LIST *first=*head,*rest=(*head)->next;
    if(!rest)
      return;

    reverse(&rest);
    first->next->next = first;
    first->next= NULL;
    *head = rest;                                                             
    // printf("   :%d",rest->data);
}

This program is working. The mentioned recursive code is for reversing the singly linked list.Consider a list L={1,2,3,4,5} as input.Consider two cases, case 1 if we uncomment statement 10, output will be data of last node i.e. 5 four times, case 2 if we comment statement no. 09 then the printf will print 5,4,3,2. My question is, in case 1 due to this statement *head=rest; why we get constant value for rest->data each call of function? If we removed statement no. 09 then printf will print different values of rest->data.
Thank you so much in advance.

2

There are 2 answers

0
mahesh cs On BEST ANSWER

Here is the answer! :-)

void reverse(LIST **head) 

{     

   01:    if(!*head)
   02:      return ;

   03:    LIST *first=*head,*rest=(*head)->next;
   04:    if(!rest)
   05:      return;
   06:    reverse(&rest); //head pointer in new function call context is a rest pointer in previous function call context.  

  07:    first->next->next = first;
  08:    first->next= NULL;
  09:    *head = rest;


  10:    // printf("   :%d",rest->data);
}

What is happening here is every time function call is returned, "*head = rest;" this statement is updating the value at location *head(which is address of head pointer) with address of rest pointer, which has effect throughout in program execution context. Every time function call returns head pointer is updated, means in every previous call rest pointer is updated (refer line 6 comment).

0
egur On

You're not connecting first to the tail of the returned list (rest). A simple way to reverse would be to use an array to store all elements and iterate the array in reverse order - like a stack.

Another options, using recursion is to return the 'tail' from reverse. Once you have the tail, it's simple to connect first to it and return that (as first is the new tail).

Here's working code using recursion:

typedef struct LIST {
    int          data;
    struct LIST *next;
} LIST;

LIST* reverse(LIST **head)
{
    LIST *first, *rest, *tail;
    if (!*head) return NULL;

    first = *head;
    rest = first->next;

    if (!rest) return first; // new tail

    tail = reverse(&rest);
    tail->next = first;
    first->next = NULL;

    *head = rest;                                                             
    return first; // new tail
    // printf("   :%d",rest->data);
}

int main(void) {
    LIST list[5] = { {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}}; 
    LIST *head = list;
    int i = 0;
    for (; i < 4; ++i) {
        list[i].next = &list[i+1];
    }
    reverse(&head);
    return 0;
}