Thread: reverse linked list

  1. #1
    Registered User
    Join Date
    Apr 2015
    Posts
    180

    reverse linked list

    I saw this implemmentation yesterday and i'am still trying to figure out how it is able to reverse the list. I get the parts that it breaks the list into first and rest and then changes pointers but that i can't see how in end we are able to change head in the caller. Can someone break it down a bit for me?
    Code:
    void recursiveReverse(Node** head)
    {
        
        Node* first, *rest;
    
        if (*head == NULL)
        {
            return;
        }
    
        first = *head;
        rest = first->nseg;
        
        if (rest == NULL)
        {
            return;
        }
        recursiveReverse(&rest);
    
        first->nseg->nseg = first;
        first->nseg = NULL;
        
        *head = rest;
            
    
        
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,666
    > but that i can't see how in end we are able to change head in the caller.
    That's why the parameter is **
    And it ends with *head = rest;

    BTW, using recursion on linked lists is a bad idea.
    It's easy to envisage a situation where you run out of stack space before you get to the end of the list.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Apr 2015
    Posts
    180
    Well i know what pointers do i don't understand the logic here. If in the end when we are dereferencing caller rest points to head of list i can see that if will work. I need to understand how it did that from the base case up to there.
    Recursion is a bad idea although i don't think its bad everywhere(isn't merge sort actually a pretty efficient with recursion on linked list?)
    Last edited by telmo_d; 10-31-2015 at 03:44 AM.

  4. #4
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,787
    Quote Originally Posted by Salem View Post
    >
    BTW, using recursion on linked lists is a bad idea.
    Maybe it's bad in practice (ok, it is unless the compiler can do TCO, I agree), but for learning purposes it's great. "Bad idea" in one context might just well be "great idea" in another...

  5. #5
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,787
    Quote Originally Posted by telmo_d View Post
    Recursion is a bad idea although i don't think its bad everywhere(isn't merge sort actually a pretty efficient with recursion on linked list?)
    I'm pretty sure he didn't mean it's a bad idea everywhere and under all circumstances.

  6. #6
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    These type of functions are a learning exercise, as opposed to being a practical solution (an iterative method would not have the potential for stack overflow and would be faster).

    if(*head == NULL) check is only needed for the initial call. The code checks for next == NULL and returns instead of calling itself again.

    first->nseg->nseg = first reverses the next (nseg) pointers in the list. Looking at the initial instance (first call) to recursiveReverse(), then first = *head = pointer to first node. first->nseg = pointer to second node, first->nseg->nseg = first sets the second nodes next (nseg) pointer to the first node. In the case of all but the initial call, first->nseg = NULL effectively does nothing, since it gets overwritten after returning to the previous call when it does first->nseg->nseg = first. In the case of the initial call, first->nseg = NULL sets the next pointer of what was the first node of the initial list is set to NULL.

    During the recursion, rest is advanced until rest == NULL, in which case the function just returns without updating the prior instance of head/rest. So as the function returns back up the call chain to the initial call, all instances of rest will end up pointing to what was the last node of the original list, including the initial call when then sets head to point to what was the last node.

    It might help to separate this into two functions, which gets rid of some unneeded checks and variables. Reverse is the initial function which calls recursiveReverse.

    Code:
    void Reverse(Node **head)
    {
    Node* first;
        /* if 0 or 1 nodes, return */
        if (*head == NULL || (*head)->next == NULL)
            return;
        first = *head;              /* save ptr to first node */
        recursiveReverse(head);     /* reverse next pointers, set head to last node */
        first->next = NULL;         /* set what was first node's next ptr to NULL */
    }
    
    void recursiveReverse(Node** head)
    {
    Node* first;
        first = *head;              /* save ptr to current node */
        if(first->next == NULL)     /* if last node, return */
            return;
        *head = first->next;        /* advance head to next node */
        recursiveReverse(head);     /* recurse until last node */
        first->next->next = first;  /* set next node's next pointer to current node */
    }
    Last edited by rcgldr; 10-31-2015 at 05:26 AM.

  7. #7
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,787
    Quote Originally Posted by telmo_d View Post
    I saw this implemmentation yesterday and i'am still trying to figure out how it is able to reverse the list. I get the parts that it breaks the list into first and rest and then changes pointers but that i can't see how in end we are able to change head in the caller. Can someone break it down a bit for me?
    If you're having trouble understanding it, there are two (at least) approaches you can take that may aid in your understanding and "light the light bulb".

    a) Using pen and paper draw a diagram of a linked list and then step through the code you've given using the linked list you drew; jotting down things along the way
    b) Add some stuff to struct Node (I am assuming it's typedef'd)... maybe 'id', or 'sequenceNumber', or 'name'... whatever. Then add a bunch of printf() function calls to the function to see what's going on (printing, maybe, the Node id or name, its address, the value of rest, the value of first, etc, etc, etc. Change the function to void recursiveReverse(Node** head, int depth) if you want to keep track of the "depth" of recursion (modifying the rest of the code appropriately of course).

    Recursion is a key concept so you may as well spend a bit of time on it exploring things.

    I'd probably go with option (b) if I couldn't visualise the concept in my head already. Nothing wrong with option (a), but you have a computer and the source code so use it

  8. #8
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    In both the original and my example code, there's no check for head == NULL before checking for *head == NULL. This could be an issue, but an uninitialized value for head could also cause a segmentation fault, so both examples assume that Node **head is valid in that *head == NULL or points to the first node of a list.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How to reverse a unidirectional linked list
    By Absurd in forum C Programming
    Replies: 5
    Last Post: 09-12-2014, 10:10 PM
  2. Linked list reverse recursively
    By gaurav_13191 in forum C Programming
    Replies: 4
    Last Post: 12-07-2011, 09:32 AM
  3. how to reverse items in linked list?
    By ilikeapplepie in forum C Programming
    Replies: 8
    Last Post: 04-09-2011, 11:15 PM
  4. Reverse a linked list, probably a simple fix.
    By csharp100 in forum C Programming
    Replies: 5
    Last Post: 11-10-2010, 11:54 PM
  5. reverse a singly linked list
    By ivandn in forum C Programming
    Replies: 15
    Last Post: 12-18-2001, 05:33 PM