简体   繁体   中英

Reversing a Linked List using recursion in C

I'm fairly new to C and I am trying to create a function to reverse a linked list, passing only the List itself as a parameter. Is this possible to do without passing a node as a parameter?

Here is my code so far, I know it does not work correctly because I cannot figure out how to make the recursive call on the rest of the list.

void reverse(LL_t *L) {
    if (L->head->next == NULL) {
        return;
    }

    node_t *rest = L->head->next;
    reverse(rest);
    node_t *q = rest->next;
    q->next = rest;
    rest->next = NULL;
}

As well here are my type definitions.

typedef struct {
    node_t *head;
    node_t *tail;
} LL_t;

typedef struct _node {
    int data;
    struct _node *next;
} node_t;

You can reverse the list with a simple loop, recursion is not needed and given your API, not appropriate.

Here is a modified version of your function:

void reverse(LL_t *L) {
    node_t *prev = NULL;
    node_t *curr = L->head;
    L->tail = curr;
    while (curr != NULL) {
        node_t *next = curr->next;
        curr->next = prev;
        prev = curr;
        curr = next;
    }
    L->head = prev;
}

If you are required to use recursion, you can test if the list is empty or limited to a singleton and do nothing, otherwise remove the head element, reverse the resulting list and append the element to the end:

void reverse(LL_t *L) {
    if (L->head != L->tail) {
        /* at least 2 elements */
        node_t *node = L->head;
        L->head = node->next;
        node->next = NULL;
        reverse(L);
        L->tail = L->tail->next = node;
    }
}

Note that this recursive approach may have undefined behavior if the list is too long as reverse will recurse too many times and cause a stack overflow .

struct node {
   int          value;
   struct node* next;
};

Non-recursive definition operating in constant stack space:

void reverse(struct node** ptr) {
   struct node* prev_ptr;
   struct node* node_ptr;

   if (prev_ptr = * ptr) {
      node_ptr = prev_ptr -> next;

      prev_ptr -> next = NULL;

      while (node_ptr) {
         struct node* temp = node_ptr -> next;

         node_ptr -> next = prev_ptr;

         prev_ptr = node_ptr;
         node_ptr = temp;
      }

      * ptr = prev_ptr;
   }
}

Extensionally equivalent recursive definition:

void reverse(struct node** ptr) {
   struct node* node_ptr;

   if (node_ptr = * ptr) {
      node_ptr -> next = NULL;

      * ptr = reverse_rec(node_ptr, node_ptr -> next);
   }
}

struct node* reverse_rec(struct node* prev_ptr, struct node* node_ptr) {
   if (! node_ptr) { return prev_ptr; }

   struct node* temp = reverse_rec(node_ptr, node_ptr -> next);
   node_ptr -> next = prev_ptr;
   return temp;
}

This works, but using recursion to reverse a list requires O(n) stack space overhead. The concept here is to advance the static instance of L->head, while keeping a local copy of head for each level of recursion. Recursion continues until the end of the list is reached, then the list is reversed using the local instances of head as reverse() returns backup the call chain.

void reverse(LL_t *L)
{
node_t *head;
    if(L->head == NULL || L->head->next == NULL)
        return;
    head = L->head;
    L->head = head->next;
    reverse(L);
    head->next->next = head;   // reverse the nodes
    head->next = NULL;
    L->tail = head;            // ends up setting tail to what was 1st node
}

//A simple program to reverse a Linked List

void reverse(struct node* head_ref) { struct node* first;

struct node* rest;
if (head_ref == NULL)
   return; 

first = head_ref;  
rest  = first->next; 
if (rest == NULL)
   return;   

reverse(rest); 
first->next->next  = first;      
first->next  = NULL;          
head_ref = rest;              

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM