Table of Contents
In this article, you will learn how to sort a linked list using the merge sort algorithm. It is one of the efficient sorting algorithms and is based on the divide and conquer approach. Since linked list cannot access elements in O(1) time as arrays do, algorithms, such as quicksort or heap sort, either cannot be applied or are inefficient. So, merge sort is a preferred sorting algorithm.
Algorithm
As already mentioned, merge sort is a divide and conquer algorithm. Therefore, it divides the list recursively into two halves, sorts them, and combines them back to get a single sorted list. Two questions can come to your mind at this point.
Divide the linked list into two halves
First, how do we divide the linked list into two halves? For that, we define a function findMid()
. It takes the head of a linked list and finds the mid using the two-pointer approach. One pointer is slow and takes one step at a time. The second fast pointer, however, takes two steps at a time. Therefore, when the fast pointer reaches the end of the list, the slow pointer will be in the middle. Finally, we return that node.
Now that we know where the middle node is, we divide the linked list into two halves. The left part contains nodes from the head to the middle node. The right half has nodes after the mid to the end.
Merge the two halves
The next question is, how do we merge the two halves? For that, we create a dummy result node. We will add items from the left and right parts in this list in sorted order. Moreover, we add items to the end using a temp pointer that always points to the result list’s end.
Initially, l and r point to the beginning of left and right halves, respectively. If the left node’s value is greater than the value at the right node, we add the left node in the result list and increment the l pointer. Otherwise, we add the right node and increment the r pointer. We continue doing this until one of the parts becomes empty. Then, we add nodes of the other half to the result list. Finally, we return it.
Consider the following image for an illustration of the merge function.
Implementation
The implementation of the Merge Sort Algorithm on a Linked List is given below.
class Node: def __init__(self, val=None, next=None): self.val = val self.next = next class LinkedList: def __init__(self): self.head = None #appends item to the linked list def add(self, val): new_node = Node(val) if self.head == None: self.head = new_node else: temp = self.head while temp.next: temp = temp.next temp.next = new_node def findMid(head): slow = head fast = head while fast.next and fast.next.next: slow = slow.next fast = fast.next.next return slow def merge(l, r): result = Node() #create a dummy node temp = None #node to add items at the end of the result list while l and r: #left node's value is less or equal to than the right node's value if l.val <= r.val: if temp==None: #no nodes in the result list, then add the first value to it result.val = l.val temp = result #update the temp pointer else: temp.next = l #add the new node after the last node in the result list temp = temp.next #update the temp to point to the end l = l.next #left node's value is greater than the right node's value else: if temp==None: result.val = r.val temp = result else: temp.next =r temp = temp.next r = r.next if l == None: #left part has been added to the list, then add the remaining right part temp.next = r if r == None: #right part has been added to the list, then add the remaining left part temp.next = l return result #return the list def mergeSort(head): if head == None: return None if head.next == None: return head mid = findMid(head) #find the mid of the given list left = head right = mid.next mid.next = None l = mergeSort(left) r = mergeSort(right) return merge(l, r) #helper function to traverse a linked list and print its values def traverse(head): temp=head while temp: print(temp.val, end=" ") temp = temp.next print() #create a linked list listt = LinkedList() #add items to the list listt.add(4) listt.add(-10) listt.add(6) listt.add(18) listt.add(0) listt.add(15) print("Before sorting") traverse(listt.head) sorted = mergeSort(listt.head) print("After sorting") traverse(sorted)
Output
Before sorting
4 -10 6 18 0 15
After sorting
-10 0 4 6 15 18
Consider the following image illustrating the steps to sort a linked list using the merge sort algorithm.