Skip to content
Related Articles

Related Articles

Improve Article
Save Article
Like Article

Alternate sorting of Linked list

  • Difficulty Level : Hard
  • Last Updated : 04 Oct, 2018

Given a linked list containing n nodes. The problem is to rearrange the nodes of the list in such a way that the data in first node is first minimum, second node is first maximum, third node is second minimum, fourth node is second maximum and so on.

Examples:

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

Input : list: 4->1->3->5->2
Output : 1->5->2->4->3

Input : list: 10->9->8->7->6->5
Output : 5->10->6->9->7->8



Approach: Following are the steps:

  1. Sort the linked list using Merge Sort technique.
  2. Split the list into front and back lists. Refer FrontBackProcedure of this post.
  3. Now, reverse the back list. Refer this post.
  4. Finally, merge the nodes of first and back lists in alternate order.




// C++ implementation of alternative sorting
// of the Linked list
#include <bits/stdc++.h>
  
using namespace std;
  
// node of a linked list
struct Node {
    int data;
    struct Node* next;
};
  
// function to get a new node
Node* getNode(int data)
{
    // allocate space for node
    Node* newNode = (Node*)malloc(sizeof(Node));
  
    // put in the data
    newNode->data = data;
    newNode->next = NULL;
  
    return newNode;
}
  
// Split the nodes of the given list into front and 
// back halves, and return the two lists using the 
// reference parameters. If the length is odd, the 
// extra node should go in the front list. Uses the 
// fast/slow pointer strategy.
void FrontBackSplit(Node* source,
                    Node** frontRef, Node** backRef)
{
    Node* fast;
    Node* slow;
    if (source == NULL || source->next == NULL) {
        // length < 2 cases
        *frontRef = source;
        *backRef = NULL;
    }
    else {
        slow = source;
        fast = source->next;
  
        // Advance 'fast' two nodes, and
        // advance 'slow' one node
        while (fast != NULL) {
            fast = fast->next;
            if (fast != NULL) {
                slow = slow->next;
                fast = fast->next;
            }
        }
  
        // 'slow' is before the midpoint in the list,
        // so split it in two at that point.
        *frontRef = source;
        *backRef = slow->next;
        slow->next = NULL;
    }
}
  
// function to merge two sorted lists in
// sorted order
Node* SortedMerge(Node* a, Node* b)
{
    Node* result = NULL;
  
    // Base cases
    if (a == NULL)
        return b;
    else if (b == NULL)
        return a;
  
    // Pick either a or b, and recur
    if (a->data <= b->data) {
        result = a;
        result->next = SortedMerge(a->next, b);
    }
    else {
        result = b;
        result->next = SortedMerge(a, b->next);
    }
  
    return result;
}
  
// sorts the linked list by changing
// next pointers (not data)
void MergeSort(Node** headRef)
{
    Node* head = *headRef;
    Node *a, *b;
  
    // Base case -- length 0 or 1
    if ((head == NULL) || (head->next == NULL))
        return;
  
    // Split head into 'a' and 'b' sublists
    FrontBackSplit(head, &a, &b);
  
    // Recursively sort the sublists
    MergeSort(&a);
    MergeSort(&b);
  
    // merge the two sorted lists together
    *headRef = SortedMerge(a, b);
}
  
// function to reverse the linked list
static void reverse(Node** head_ref)
{
    Node* prev = NULL;
    Node* current = *head_ref;
    Node* next;
  
    while (current != NULL) {
        next = current->next;
        current->next = prev;
        prev = current;
        current = next;
    }
  
    *head_ref = prev;
}
  
// function to alternately merge two lists
void alternateMerge(Node* head1, Node* head2)
{
    Node *p, *q;
    while (head1 != NULL && head2 != NULL) {
  
        // merging nodes alternately by
        // making the desired links
        p = head1->next;
        head1->next = head2;
        head1 = p;
        q = head2->next;
        head2->next = head1;
        head2 = q;
    }
}
  
// function for alternative sort of the
// linked list
Node* altSortForLinkedList(Node* head)
{
    // sort the linked list
    MergeSort(&head);
  
    Node *front, *back;
  
    // Split head into 'front' and 'back' sublists
    FrontBackSplit(head, &front, &back);
  
    // reversing the 'back' list
    reverse(&back);
  
    // merging the nodes of 'front' and 'back'
    // lists alternately
    alternateMerge(front, back);
  
    // required head of final list
    return front;
}
  
// Function to print nodes in
// a given linked list
void printList(Node* head)
{
    while (head != NULL) {
        cout << head->data << " ";
        head = head->next;
    }
}
  
// Driver program to test above
int main()
{
    // linked list: 10->9->8->7->6->5
    Node* head = getNode(10);
    head->next = getNode(9);
    head->next->next = getNode(8);
    head->next->next->next = getNode(7);
    head->next->next->next->next = getNode(6);
    head->next->next->next->next->next = getNode(5);
  
    cout << "Original list: ";
    printList(head);
  
    head = altSortForLinkedList(head);
  
    cout << "\nModified list: ";
    printList(head);
  
    return 0;
}


Output:

Original list: 10 9 8 7 6 5
Modified list: 5 10 6 9 7 8

Time Complexity: O(n*logn).




My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!