Open In App

How to Sort a LinkedList in Java?

Last Updated : 14 Sep, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

A Linked List is a linear data structure, in which the elements are not stored at contiguous memory locations.

Sorting the nodes of a Singly Linked list in ascending order:

Original-List
Original List
SortedList
Sorted List

We can sort the LinkedList by many sorting techniques:

  1. Selection Sort
  2. Insertion sort
  3. Quick sort
  4. Merge sort
 

Method 1: Sort Linked List using Selection Sort

  • In Selection Sort, we maintain two pointers: current and index.
  • Initially, current points to the head node, and index will point to the node next to current.
  • We traverse through the list until current points to null.
  • For each current node, index traverses from the next node of current until null.
  • The value of the current node is compared with every value from its next node until the end of the list.
  • If the value in index is smaller than the value in current, we swap the values.
  • This way, the smallest value comes to the current index.
Java
public class SortList {

    // Represent a node of the singly linked list
    class Node {
        int data;
        Node next;

        public Node(int data) {
            this.data = data;
            this.next = null;
        }
    }

    // Represent the head of the singly linked list
    public Node head = null;

    // addNode() will add a new node to the list
    public void addNode(int data) {
        // Create a new node
        Node newNode = new Node(data);

        // If the list is empty, make the new node as head
        if (head == null) {
            head = newNode;
        } else {
            // Traverse to the last node and add the new node
            Node current = head;
            while (current.next != null) {
                current = current.next;
            }
            current.next = newNode;
        }
    }

    // sortList() will sort nodes of the list in ascending order using Selection Sort
    public void sortList() {
        Node current = head;

        // Traverse through the list
        while (current != null) {
            Node index = current.next;
            Node min = current;

            // Find the minimum element in the unsorted part of the list
            while (index != null) {
                if (index.data < min.data) {
                    min = index;
                }
                index = index.next;
            }

            // Swap the minimum element with the current element
            int temp = current.data;
            current.data = min.data;
            min.data = temp;

            // Move to the next node
            current = current.next;
        }
    }

    // display() will display all the nodes present in the list
    public void display() {
        Node current = head;
        if (head == null) {
            System.out.println("List is empty");
            return;
        }
        while (current != null) {
            // Print each node's data
            System.out.print(current.data + " ");
            current = current.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        SortList sList = new SortList();

        // Add data to the list
        sList.addNode(8);
        sList.addNode(3);
        sList.addNode(7);
        sList.addNode(4);

        // Display original list
        System.out.println("Original list:");
        sList.display();

        // Sort the list using Selection Sort
        sList.sortList();

        // Display sorted list
        System.out.println("Sorted list:");
        sList.display();
    }
}

Output
Original list:
8 3 7 4 
Sorted list:
3 4 7 8 

Time complexity: O(n ^ 2)
Auxiliary Space: O(1)

Method 2: Sort Linked List using Insertion Sort 

  • In the Insertion sort technique, we assume that all the elements before the current element in the list is already sorted, and we begin with the current element.
  • The current element is compared with all the elements before it and swapped if not in order. This process is repeated for all the subsequent elements.
  • In general, the Insertion sort technique compares each element with all of its previous elements and sorts the element to place it in its proper position.

As already mentioned, the Insertion sort technique is more feasible for a smaller set of data, and thus arrays with a few elements can be sorted using efficiently Insertion sort.

Insertion sort is especially useful in sorting linked list data structures. As you know, Linked lists have pointers pointing to its next element (singly linked list) and previous element (double linked list). This makes it easier to keep track of the previous and next elements. 

Java
// Java program to sort Linked List using Insertion Sort

public class LinkedlistIS {
    node head;
    node sorted;

    class node {
        int val;
        node next;

        public node(int val) { this.val = val; }
    }

    void push(int val)
    {
        // allocate node
        node newnode = new node(val);

        // link the old list of the new node
        newnode.next = head;

        // move the head to point to the new node
        head = newnode;
    }

    // function to sort a singly linked list using insertion
    // sort
    void insertionSort(node headref)
    {
        // Initialize sorted linked list
        sorted = null;
        node current = headref;

        // Traverse the given linked list and insert every
        // node to sorted
        while (current != null) {
            // Store next for next iteration
            node next = current.next;

            // insert current in sorted linked list
            sortedInsert(current);

            // Update current
            current = next;
        }

        // Update head_ref to point to sorted linked list
        head = sorted;
    }

    // function to insert a new_node in a list. Note that
    // this function expects a pointer to head_ref as this
    // can modify the head of the input linked list
    // (similar to push())
    void sortedInsert(node newnode)
    {
        // Special case for the head end
        if (sorted == null || sorted.val >= newnode.val) {
            newnode.next = sorted;
            sorted = newnode;
        }
        else {
            node current = sorted;

            // Locate the node before the point of insertion
            while (current.next != null
                   && current.next.val < newnode.val) {
                current = current.next;
            }

            newnode.next = current.next;
            current.next = newnode;
        }
    }

    // Function to print linked list
    void printlist(node head)
    {
        while (head != null) {
            System.out.print(head.val + " ");
            head = head.next;
        }
    }

    // Driver program to test above functions
    public static void main(String[] args)
    {
        LinkedlistIS list = new LinkedlistIS();

        list.push(4);
        list.push(7);
        list.push(3);
        list.push(8);

        System.out.println("Linked List before Sorting..");
        list.printlist(list.head);

        list.insertionSort(list.head);

        System.out.println("\nLinkedList After sorting");
        list.printlist(list.head);
    }
}

Output
Linked List before Sorting..
8 3 7 4 
LinkedList After sorting
3 4 7 8

Time complexity: O(n ^ 2)
Auxiliary Space: O(1)

Method 3: Sort Linked List using Quick Sort

Quick sort follows divide and conquer approach. It picks an element as pivot and partitions the given array around the picked pivot.

The key process in quickSort is partition(). Target of partitions is, given an array and an element x of array as pivot, put x at its correct position in sorted array and put all smaller elements (smaller than x) before x, and put all greater elements (greater than x) after x. All this should be done in linear time.

Quick sort is preferred over merge sort as Quick sort is an in-place algorithm (meaning, no additional memory space required).

Java
// Java program for Quick Sort on Singly Linked List

public class QuickSortLinkedList {
    static class Node {
        int data;
        Node next;

        Node(int d)
        {
            this.data = d;
            this.next = null;
        }
    }

    Node head;

    void addNode(int data)
    {
        if (head == null) {
            head = new Node(data);
            return;
        }

        Node curr = head;

        while (curr.next != null)
            curr = curr.next;

        Node newNode = new Node(data);
        curr.next = newNode;
    }

    void printList(Node n)
    {
        while (n != null) {
            System.out.print(n.data);
            System.out.print(" ");
            n = n.next;
        }
    }

    // takes first and last node,
    // but do not break any links in
    // the whole linked list
    Node paritionLast(Node start, Node end)
    {
        if (start == end || start == null || end == null)

            return start;

        Node pivot_prev = start;
        Node curr = start;
        int pivot = end.data;

        // iterate till one before the end,
        // no need to iterate till the end
        // because end is pivot
        while (start != end) {
            if (start.data < pivot) {
                // keep tracks of last modified item
                pivot_prev = curr;
                int temp = curr.data;
                curr.data = start.data;
                start.data = temp;
                curr = curr.next;
            }

            start = start.next;
        }

        // swap the position of curr i.e.
        // next suitable index and pivot
        int temp = curr.data;
        curr.data = pivot;
        end.data = temp;

        // return one previous to current
        // because current is now pointing to pivot
        return pivot_prev;
    }

    void sort(Node start, Node end)
    {
        if (start == end)
            return;

        // split list and partition recurse
        Node pivot_prev = paritionLast(start, end);

        sort(start, pivot_prev);

        // if pivot is picked and moved to the start,
        // that means start and pivot is same
        // so pick from next of pivot
        if (pivot_prev != null && pivot_prev == start)
            sort(pivot_prev.next, end);

        // if pivot is in between of the list,
        // start from next of pivot,
        // since we have pivot_prev, so we move two nodes
        else if (pivot_prev != null
                 && pivot_prev.next != null)
            sort(pivot_prev.next.next, end);
    }

    // Driver Code
    public static void main(String[] args)
    {
        QuickSortLinkedList list
            = new QuickSortLinkedList();

        list.addNode(8);
        list.addNode(3);
        list.addNode(7);
        list.addNode(4);

        Node n = list.head;

        while (n.next != null)
            n = n.next;

        System.out.println("Original List: ");
        list.printList(list.head);

        list.sort(list.head, n);

        System.out.println("\nSorted List: ");
        list.printList(list.head);
    }
}

Output
Original List: 
8 3 7 4 
Sorted List: 
3 4 7 8

Time complexity: O(n ^ 2)
Auxiliary Space: O(1)

Method 4: Sort Linked List using Merge Sort

Merge sort is often preferred for sorting a linked list. The slow random-access performance of a linked list makes some other algorithms (such as quicksort) perform poorly, and others (such as heapsort) completely impossible.

Merge Sort is a Divide and Conquer algorithm. It divides the input array into two halves, calls itself for the two halves, and then merges the two sorted halves. The merge() function is used for merging two halves. The merge(arr, l, m, r) is a key process that assumes that arr[l..m] and arr[m+1..r] are sorted and merges the two sorted sub-arrays into one.

  • Let head be the first node of the linked list to be sorted and headRef be the pointer to head.
  • Note that we need a reference to head in MergeSort() as the below implementation changes next links to sort the linked lists (not data at the nodes), so head node has to be changed if the data at original head is not the smallest value in linked list.
Java
// Java program to sort linkedList using Merge Sort

public class linkedList {
    node head = null;

    // node a, b;
    static class node {
        int val;
        node next;

        public node(int val) { this.val = val; }
    }

    node sortedMerge(node a, node b)
    {
        node result = null;

        // Base cases
        if (a == null)
            return b;
        if (b == null)
            return a;

        // Pick either a or b, and recur
        if (a.val < b.val) {
            result = a;
            result.next = sortedMerge(a.next, b);
        }
        else {
            result = b;
            result.next = sortedMerge(a, b.next);
        }

        return result;
    }

    node mergeSort(node h)
    {
        // Base case : if head is null
        if (h == null || h.next == null) {
            return h;
        }

        // get the middle of the list
        node middle = getMiddle(h);
        node nextofmiddle = middle.next;

        // set the next of middle node to null
        middle.next = null;

        // Apply mergeSort on left list
        node left = mergeSort(h);

        // Apply mergeSort on right list
        node right = mergeSort(nextofmiddle);

        // Merge the left and right lists
        node sortedlist = sortedMerge(left, right);

        return sortedlist;
    }

    // Utility function to get the middle of the linked list
    public static node getMiddle(node head)
    {
        if (head == null)
            return head;

        node slow = head, fast = head;

        while (fast.next != null
               && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }

        return slow;
    }

    void push(int new_data)
    {
        // allocate node
        node new_node = new node(new_data);

        // link the old list of the new node
        new_node.next = head;

        // move the head to point to the new node
        head = new_node;
    }

    // Utility function to print the linked list
    void printList(node headref)
    {
        while (headref != null) {
            System.out.print(headref.val + " ");
            headref = headref.next;
        }
    }

    public static void main(String[] args)
    {

        linkedList li = new linkedList();

        li.push(4);
        li.push(7);
        li.push(3);
        li.push(8);

        System.out.print("\nOriginal List: \n");
        li.printList(li.head);

        // Apply merge Sort
        li.head = li.mergeSort(li.head);

        System.out.print("\nSorted List: \n");
        li.printList(li.head);
    }
}

Output
Original List: 
8 3 7 4 
Sorted List: 
3 4 7 8

Time complexity: O(n log n)
Auxiliary Space: O(1)

Method 5: Sort Linked List using Bubble Sort

Bubble Sort is a simple sorting algorithm that works by repeatedly stepping through the list, comparing adjacent elements, and swapping them if they are in the wrong order.

Here's how Bubble Sort works:

  • Imagine you have a list of numbers.
  • Start at the beginning of the list.
  • Compare the first two numbers. If the first number is greater than the second number, swap them.
  • Move to the next pair of numbers and repeat the comparison and swapping process.
  • Continue this process until you reach the end of the list.
  • After the first pass through the list, the largest number will "bubble up" to the end of the list.
  • Repeat steps 2-6 for the remaining unsorted portion of the list, but now you don't need to include the last (already sorted) element.
  • Keep repeating this process until the entire list is sorted.
Java
public class SortList {

    // Represent a node of the singly linked list
    class Node {
        int data;
        Node next;

        public Node(int data) {
            this.data = data;
            this.next = null;
        }
    }

    // Represent the head of the singly linked list
    public Node head = null;

    // addNode() will add a new node to the list
    public void addNode(int data) {
        // Create a new node
        Node newNode = new Node(data);

        // If the list is empty, make the new node as head
        if (head == null) {
            head = newNode;
        } else {
            // Traverse to the last node and add the new node
            Node current = head;
            while (current.next != null) {
                current = current.next;
            }
            current.next = newNode;
        }
    }

    // sortList() will sort nodes of the list in ascending order using Bubble Sort
    public void sortList() {
        Node current;
        Node index = null;
        int temp;

        // If list is empty, return
        if (head == null) {
            return;
        } else {
            // Traverse through the list
            for (current = head; current.next != null; current = current.next) {
                // Traverse through the unsorted part of the list
                for (index = current.next; index != null; index = index.next) {
                    // Swap data if the current element is greater than the next element
                    if (current.data > index.data) {
                        temp = current.data;
                        current.data = index.data;
                        index.data = temp;
                    }
                }
            }
        }
    }

    // display() will display all the nodes present in the list
    public void display() {
        Node current = head;
        if (head == null) {
            System.out.println("List is empty");
            return;
        }
        while (current != null) {
            // Print each node's data
            System.out.print(current.data + " ");
            current = current.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        SortList sList = new SortList();

        // Add data to the list
        sList.addNode(8);
        sList.addNode(3);
        sList.addNode(7);
        sList.addNode(4);

        // Display original list
        System.out.println("Original list:");
        sList.display();

        // Sort the list using Bubble Sort
        sList.sortList();

        // Display sorted list
        System.out.println("Sorted list:");
        sList.display();
    }
}

Output
Original list:
8 3 7 4 
Sorted list:
3 4 7 8 

Time complexity: O(n^2)

Space complexity: O(1)



Next Article
Article Tags :
Practice Tags :

Similar Reads