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:
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:
- Sort the linked list using Merge Sort technique.
- Split the list into front and back lists. Refer FrontBackProcedure of this post.
- Now, reverse the back list. Refer this post.
- Finally, merge the nodes of first and back lists in alternate order.
Implementation
CPP
// 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).