Reverse a sublist of linked list

We are given a linked list and positions m and n. We need to reverse the linked list from position m to n.

Examples:

Input : 10->20->30->40->50->60->70->NULL
        m = 3, n = 6
Output : 10->20->60->50->40->30->70->NULL

Input :  1->2->3->4->5->6->NULL 
         m = 2, n = 4
Output : 1->4->3->2->5->6->NULL

To reverse the linked list from position m to n, we find addresses of start and end position of the linked list by running a loop, and then we unlink this part from the rest of the list and then use the normal linked list reverse function which we have earlier used for reversing the complete linked list, and use it to reverse the portion of the linked list which need to be reversed. After reversal, we again attach the portion reversed to the main list.

filter_none

edit
close

play_arrow

link
brightness_4
code

// C program to reverse a linked list
// from position m to position n
#include <stdio.h>
#include <stdlib.h>
  
// Linked list node
struct Node {
    int data;
    struct Node* next;
};
  
// the standard reverse function used
// to reverse a linked list
struct Node* reverse(struct Node* head)
{
    struct Node* prev = NULL;    
    struct Node* curr = head;
  
    while (curr) {
        struct Node* next = curr->next;
        curr->next = prev;
        prev = curr;
        curr = next;
    }
    return prev;
}
  
// function used to reverse a linked list
// from position m to n which uses reverse
// function
Node* reverseBetween(Node* head, int m, int n)
{
    if (m == n)
        return head;
  
    // revs and revend is start and end respectively
    // of the portion of the linked list which
    // need to be reversed. revs_prev is previous
    // of starting position and revend_next is next
    // of end of list to be reversed.
    Node* revs = NULL, *revs_prev = NULL;
    Node* revend = NULL, *revend_next = NULL;
  
    // Find values of above pointers.
    int i = 1;
    Node* curr = head;
    while (curr && i <= n) {
        if (i < m)
            revs_prev = curr;
  
        if (i == m)
            revs = curr;
  
        if (i == n) {
            revend = curr;
            revend_next = curr->next;
        }
  
        curr = curr->next;
        i++;
    }
    revend->next = NULL;
  
    // Reverse linked list starting with
    // revs.
    revend = reverse(revs);
  
    // If starting position was not head
    if (revs_prev)
        revs_prev->next = revend;
  
    // If starting position was head
    else
        head = revend;
  
    revs->next = revend_next;
    return head;
}
  
void print(struct Node* head)
{
    while (head != NULL) {
        printf("%d ", head->data);
        head = head->next;
    }
    printf("\n");
}
  
// function to add a new node at the
// begining of the list
void push(struct Node** head_ref, int new_data)
{
    struct Node* new_node = new Node;
    new_node->data = new_data;
    new_node->next = (*head_ref);
    (*head_ref) = new_node;
}
  
// Driver code
int main()
{
    struct Node* head = NULL;
    push(&head, 70);
    push(&head, 60);
    push(&head, 50);
    push(&head, 40);
    push(&head, 30);
    push(&head, 20);
    push(&head, 10);
    reverseBetween(head, 3, 6);
    print(head);
    return 0;
}

chevron_right


Output:

10 20 60 50 40 30 70 

This article is contributed by Akshit Agarwal. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.



My Personal Notes arrow_drop_up


Article Tags :
Practice Tags :


4


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.