Given a linked list, sort it using the merge sort algorithm.
Practice this problem
Merge sort is an efficient, general-purpose sorting algorithm that produces a stable sort, which means that the implementation preserves the input order of equal elements in the sorted output. It is a comparison sort, i.e., it can sort items of any type for which a less-than relation is defined.
Merge sort is a Divide and Conquer algorithm. Like all divide-and-conquer algorithms, the merge sort algorithm splits the list into two sublists. Then it recursively sorts each sublist and finally merges both sorted lists together to form the answer. The following solution uses the frontBackSplit[] and sortedMerge[] method to solve this problem efficiently. We have already covered them in detail in previous posts.
The algorithm can be implemented as follows in C, Java, and Python:
C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | #include #include // A Linked List Node struct Node { int data; struct Node* next; }; // Helper function to print a given linked list void printList[struct Node* head] { struct Node* ptr = head; while [ptr] { printf["%d > ", ptr->data]; ptr = ptr->next; } printf["NULL\n"]; } // Helper function to insert a new node at the beginning of the linked list void push[struct Node** head, int data] { struct Node* newNode = [struct Node*]malloc[sizeof[struct Node]]; newNode->data = data; newNode->next = *head; *head = newNode; } // Takes two lists sorted in increasing order and merge their nodes // to make one big sorted list, which is returned struct Node* sortedMerge[struct Node* a, struct Node* b] { // base cases if [a == NULL] { return b; } else if [b == NULL] { return a; } struct Node* result = NULL; // pick either `a` or `b`, and recur if [a->data data] { result = a; result->next = sortedMerge[a->next, b]; } else { result = b; result->next = sortedMerge[a, b->next]; } return result; } /* Split the given list's nodes 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. It uses the fast/slow pointer strategy */ void frontBackSplit[struct Node* source, struct Node** frontRef, struct Node** backRef] { // if the length is less than 2, handle it separately if [source == NULL || source->next == NULL] { *frontRef = source; *backRef = NULL; return; } struct Node* slow = source; struct Node* 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; } // Sort a given linked list using the merge sort algorithm void mergesort[struct Node** head] { // base case length 0 or 1 if [*head == NULL || [*head]->next == NULL] { return; } struct Node* a; struct Node* b; // split `head` into `a` and `b` sublists frontBackSplit[*head, &a, &b]; // recursively sort the sublists mergesort[&a]; mergesort[&b]; // answer = merge the two sorted lists *head = sortedMerge[a, b]; } int main[void] { // input keys int keys[] = { 6, 8, 4, 3, 1, 9 }; int n = sizeof[keys]/sizeof[keys[0]]; struct Node* head = NULL; for [int i = 0; i 3 > 4 > 6 > 8 > 9 > NULL Java
|