Insertion Sort List

Updated on 03 June, 2025
Insertion Sort List header image

Problem Statement

The task is to sort a singly linked list using the insertion sort algorithm and return the head of the sorted linked list. Insertion sort, a straightforward and intuitive sorting algorithm, works by building a sorted array or list one item at a time by repeatedly removing an element from the input data and finding the appropriate spot for it within the already sorted section.

This method treats the list in two parts: the already sorted section, which initially contains only the first element, and the unsorted section, which includes all other elements. To integrate an element from the unsorted section, the algorithm removes it and inserts it into the correct position in the sorted section. This process repeats until all elements are neatly allocated in the sorted section, and the input list is fully sorted.

Examples

Example 1

Input:

head = [4,2,1,3]

Output:

[1,2,3,4]

Example 2

Input:

head = [-1,5,3,4,0]

Output:

[-1,0,3,4,5]

Constraints

  • The number of nodes in the list is in the range [1, 5000].
  • -5000 <= Node.val <= 5000

Approach and Intuition

The insertion sort starts by assuming that the first element of the linked list is already sorted. Then, it proceeds with the following steps:

  1. Prepare a "dummy" node before the head of the original list, which helps handle edge cases, such as inserting a node at the head.
  2. Traverse the original linked list, beginning with the second element (since the first is assumed sorted).
  3. For each node in the original list, compare its value with those in the sorted part, from left to right, to find the appropriate insertion point.
  4. Adjust the pointers to accommodate the newly inserted node in the sorted list without losing the rest of the unsorted nodes.

The following examples illustrate this process:

  • Example 1:

    • Input: head = [4,2,1,3]
    • Processing:
      • Start with 4 as the sorted part.
      • Insert 2, 1, and 3 in successive steps into their appropriate positions within the sorted part.
    • Output: [1,2,3,4] – List after sorting using insertion sort.
  • Example 2:

    • Input: head = [-1,5,3,4,0]
    • Processing:
      • Beginning with -1 as the sorted part.
      • Insert 5, 3, 4, and 0 into the sorted part, making sure to maintain order after each insertion.
    • Output: [-1,0,3,4,5] – A list rearranged from least to greatest value.

Constraints Contextualization:

  • The constraint that the list may contain up to 5000 nodes means our approach must be efficient enough to handle relatively large lists.
  • The value range of the nodes, being from -5000 to 5000, does not complicate our insertion logic, which is primarily concerned with relational rather than absolute values.

Solutions

  • C++
  • Java
  • C
  • JavaScript
  • Python
cpp
class Solution {
public:
    ListNode* sortLinkedList(ListNode* start) {
        ListNode* placeholder = new ListNode();
        ListNode* pointer = start;
        while (pointer != NULL) {
            ListNode* temp = placeholder;
            while (temp->next != NULL && temp->next->val <= pointer->val) {
                temp = temp->next;
            }
            ListNode* subsequent = pointer->next;
            pointer->next = temp->next;
            temp->next = pointer;
            pointer = subsequent;
        }
        return placeholder->next;
    }
};

This code offers a C++ implementation of the insertion sort algorithm specifically adapted to sort a singly linked list. The method sortLinkedList accepts a pointer to the beginning of the linked list and returns a pointer to the sorted linked list.

Here's an outline of how this function operates:

  • A new placeholder node, placeholder, is created to ease the insertion process by temporarily holding the sorted part of the list.
  • A pointer is used to traverse through the original list, starting from its first node.
  • For each node pointed to by pointer, iterate through the already sorted part of the list (starting from placeholder) using another pointer, temp.
  • Locate the proper position in the sorted list to insert the current node by checking if the value of temp->next is less than or equal to the current node's value.
  • Insert the current node (pointer) in its correct position:
    • Disconnect it from the original list.
    • Adjust pointers so it links correctly within the sorted part.
  • Move the pointer to the next node in the original list to continue the sorting process.
  • Finally, return the next node of the placeholder, which points to the head of the newly sorted linked list.

This method effectively reorders the nodes without allocating any new nodes except for an initial temporary node, ensuring a space-efficient sorting process while maintaining the original data intact.

java
class Solution {
    public ListNode sortInsertion(ListNode headNode) {
        ListNode sortedHead = new ListNode();
        ListNode iterate = headNode;

        while (iterate != null) {
            ListNode positionFinder = sortedHead;

            while (positionFinder.next != null && positionFinder.next.val <= iterate.val) {
                positionFinder = positionFinder.next;
            }

            ListNode upcomingNode = iterate.next;
            iterate.next = positionFinder.next;
            positionFinder.next = iterate;
            iterate = upcomingNode;
        }

        return sortedHead.next;
    }
}

The given Java solution sorts a linked list using the insertion sort algorithm. Insertion sort is a simple sorting algorithm that builds the final sorted array (or list in this case) one item at a time. It is much less efficient on large lists than more advanced algorithms such as quicksort, heapsort, or merge sort. However, it provides an excellent method to sort a linked list due to its inherent mechanism, which does not require backtracking.

  • Perform the following steps to understand the provided solution's mechanism:

    • Create a new placeholder for the start of the sorted list (sortedHead), initializing an empty ListNode.
    • Traverse through each node of the original list (headNode) with a pointer named iterate.
    • For each node that iterate points to, find the correct position in the sorted list to insert the node. This is done using another pointer, positionFinder, which starts from the beginning of the sorted list (sortedHead).
    • Slide down the sorted list using positionFinder until finding the spot where the current node (iterate's node) should reside. This condition is met when no further node fits the criteria, or the next node's value exceeds the current value.
    • Interchange references to insert the node from the unsorted part into the correct position in the sorted list.
    • Continue this for every node until all nodes are sorted, ultimately omitting the placeholder node (sortedHead).
  • The function would return sortedHead.next, which points to the head of the newly sorted linked list. Consequently, the original list structure is repurposed to form a sorted list based on node values, achieving the sorting through in-place node rearrangement without additional memory for array manipulation.

c
struct ListNode* sortLinkedList(struct ListNode* headNode) {
    struct ListNode* sortedHead = malloc(sizeof(struct ListNode));
    sortedHead->next = NULL;
    struct ListNode* currentNode = headNode;
    while (currentNode != NULL) {
        struct ListNode* positionNode = sortedHead;
        while (positionNode->next != NULL && positionNode->next->val <= currentNode->val) {
            positionNode = positionNode->next;
        }
        struct ListNode* nextNode = currentNode->next;
        currentNode->next = positionNode->next;
        positionNode->next = currentNode;
        currentNode = nextNode;
    }
    return sortedHead->next;
}

The code provided implements the insertion sort algorithm for sorting a linked list in C. The function sortLinkedList takes a pointer to the head of an unsorted singly linked list and returns a new list that is sorted in ascending order. Below is a step-by-step breakdown of how this function operates:

  1. Initial setup involves creating a helper node, sortedHead, which acts as a placeholder to facilitate easier insertion into the sorted part of the list. This node initially points to NULL.

  2. A currentNode pointer starts at the head of the unsorted list and traverses each node.

  3. For each currentNode, the code iterates through the already sorted list (starting from sortedHead) to find the correct insert position. This is achieved using a positionNode which moves through the sorted list as long as its next node's value is less than or equal to the value of currentNode.

  4. Once the appropriate position is located, currentNode is inserted after positionNode:

    • nextNode temporarily holds the next node in the unsorted list.
    • The current node is linked into the sorted list by adjusting pointers.
    • The traversal pointer (currentNode) then moves to nextNode, proceeding to the next node in the original list.
  5. This process repeats until all nodes from the original list are examined and inserted appropriately into the sorted list.

  6. Finally, the function returns the next node to sortedHead, effectively the head of the newly sorted list, excluding the initial placeholder node.

This efficient handling of linked list elements ensures that all nodes are sorted without the need for additional data structures, with the operations primarily involving re-linking existing nodes in a different order. This solution is robust for various list conditions, including empty or single-element lists.

js
var sortLinkedList = function (headNode) {
    let dummyNode = new ListNode();
    let current = headNode;
    while (current !== null) {
        let prevNode = dummyNode;
        while (prevNode.next !== null && prevNode.next.val <= current.val) {
            prevNode = prevNode.next;
        }
        let nextNode = current.next;
        current.next = prevNode.next;
        prevNode.next = current;
        current = nextNode;
    }
    return dummyNode.next;
};

The provided JavaScript code efficiently sorts a linked list using the insertion sort algorithm. To understand the solution implemented in the code:

  1. Initiate a dummyNode to facilitate easier handling of the head of the linked list, particularly when insertion happens at the head.
  2. Define current to navigate through the original list from the headNode.

Proceed with the sorting process with the following detailed steps:

  1. Use a while loop to process each node in the list denoted by current. The loop continues until current becomes null, indicating the end of the list.
  2. Inside the loop, another nested while loop is utilized. Define prevNode starting from dummyNode to find the correct position to insert the current node. This loop continues as long as the next node of prevNode exists and its value is less than or equal to the value of current.
  3. Set nextNode to point to the next node of current, which will become the new current node in the subsequent iteration.
  4. Insert current into the new position by adjusting the next pointers: current.next will point to prevNode.next and then update prevNode.next to point to current.
  5. Move to the next node in the original list by updating current to nextNode.

The sorted linked list is obtained from dummyNode.next, effectively skipping the dummy node used for insertion handling.

This code provides a robust method for sorting elements of a linked list where space complexity is minimized by reusing existing nodes, and the algorithm manages in-place sorting with a time complexity typically of O(n^2) in the worst case. This method is particularly useful when you need a stable sort without additional memory overhead, suitable for applications with limited memory resources.

python
class Solution:
    def sortLinkedList(self, node: ListNode) -> ListNode:
        placeholder = ListNode()
        point = node

        while point:
            prev_node = placeholder

            # Locate where to insert the current node
            while prev_node.next and prev_node.next.val <= point.val:
                prev_node = prev_node.next

            subsequent = point.next
            # Perform the insert operation
            point.next = prev_node.next
            prev_node.next = point

            # Advance to the next node in the list
            point = subsequent

        return placeholder.next

The provided Python code implements the insertion sort algorithm to sort a linked list. The insertion sort is a straightforward algorithm that builds the final sorted linked list one item at a time. It is much less efficient on large lists than more advanced algorithms such as quicksort or merge sort. However, the advantage of insertion sort is its simplicity and that it sorts in place, using a constant amount of additional space.

Here's a breakdown of the process:

  1. A placeholder node is created to act as the start of the sorted linked list.
  2. An iteration is initialized with the first node of the provided list.
  3. During each iteration of the while loop, the algorithm looks for the correct position to insert the current node to maintain the order:
    • It systematically compares the current node's value with the sorted nodes' values.
    • Finds the correct insertion point.
  4. Once the correct position is identified:
    • The current node is then linked appropriately by adjusting the next pointers.
  5. The link adjustment is made:
    • The current node points to its succeeding nodes in the already-sorted portion of the linked list ensuring order is maintained.
    • The pointer of the preceding sorted node is adjusted to point to the current node effectively inserting it.
  6. The pointer moves to the next node in the list and the process is repeated until all nodes are processed and placed in order.
  7. The sorted linked list, which starts from the placeholder's next node, is then returned.

This code effectively allows a linked list to be sorted in ascending order without using additional lists or arrays, only rearranging the nodes by changing their pointers.

Comments

No comments yet.