diff --git a/src/main/java/com/thealgorithms/datastructures/lists/QuickSortLinkedList.java b/src/main/java/com/thealgorithms/datastructures/lists/QuickSortLinkedList.java new file mode 100644 index 000000000000..36b6e9c62cbe --- /dev/null +++ b/src/main/java/com/thealgorithms/datastructures/lists/QuickSortLinkedList.java @@ -0,0 +1,170 @@ +package com.thealgorithms.datastructures.lists; +/* + * + * @aurthor - Prabhat-Kumar-42 + * @github - https://github.com/Prabhat-Kumar-42 + * + * Problem : + * QuickSort on Linked List + * + * Note: Taking head as pivot in current implementation. + * N represents NULL node + * Example: + * + * -> Given Linked List : + * 5 -> 3 -> 8 -> 1 -> 10 -> 2 -> 7 -> 4 -> 9 -> 6 + * + * -> How Sorting will work according to the QuickSort Algo written below + * + * current pivot : 5 + * List lessThanPivot : 3 -> 1 -> 2 -> 4 + * List greaterThanPivot : 5 -> 8 -> 10 -> 7 -> 9 -> 6 + * + * -> reccur for lessThanPivot and greaterThanPivot + * + * lessThanPivot : + * current pivot : 3 + * lessThanPivot : 1 -> 2 + * greaterThanPivot : 4 + * + * greaterThanPivot: + * current pivot : 5 + * lessThanPivot : null + * greaterThanPivot : 8 -> 10 -> 7 -> 9 -> 6 + * + * By following the above pattern, reccuring tree will form like below : + * + * List-> 5 -> 3 -> 8 -> 1 -> 10 -> 2 -> 7 -> 4 -> 9 -> 6 + * + * Pivot : 5 + * /\ + * / \ + * / \ + * / \ + * / \ + * List: (3 -> 1 -> 2 -> 4) (5 -> 8 -> 10 -> 7 -> 9 -> 6) + * Pivot : 3 5 + * /\ /\ + * / \ / \ + * / \ / \ + * / \ / \ + * List: (1 -> 2) (4) (N) (8 -> 10 -> 7 -> 9 -> 6) + * Pivot: 1 4 8 + * /\ /\ /\ + * / \ / \ / \ + * / \ / \ / \ + * List: (N) (2) (N) (N) (6 -> 7) (9 -> 10) + * Pivot: 2 6 9 + * /\ /\ /\ + * / \ / \ / \ + * / \ / \ / \ + * List: (N) (N) (N) (7) (N) (10) + * Pivot: 7 10 + * /\ /\ + * / \ / \ + * / \ / \ + * (N) (N) (N) (N) + * + * + * -> After this the tree will reccur back (or backtrack) + * and the returning list from left and right subtree will attach + * themselves around pivot. + * i.e. , + * (listFromLeftSubTree) -> (Pivot) -> (listFromRightSubtree) + * + * This will continue until whole list is merged back + * + * eg : + * Megring the above Tree back we get : + * + * List: (1 -> 2) (4) (6 -> 7) (9 -> 10) + * \ / \ / + * \ / \ / + * \ / \ / + * \ / \ / + * \ / \ / + * \ / \ / + * \ / \ / + * Pivot: 3 8 + * List: (1 -> 2 -> 3 -> 4) (6 -> 7 -> 8 -> 9 -> 10) + * \ / + * \ / + * \ / + * \ / + * \ / + * \ / + * \ / + * \/ + * Pivot: 5 + * List: (1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10) + * + * + * -> This will result in a sorted Linked List + */ + +public class QuickSortLinkedList { + + private SinglyLinkedList list = null; // Linked list + private Node head = null; // head of the list + // Counstructor + public QuickSortLinkedList(SinglyLinkedList list) { + this.list = list; + this.head = list.getHead(); + } + + // Function to sort a linked list using the Quick Sort algorithm + public void sortList() { + head = sortList(head); + list.setHead(head); + } + // helper function to apply QuickSort to the stored list + public Node sortList(Node head) { + if (head == null || head.next == null) { + return head; + } + + // Choose the first element as the pivot + Node pivot = head; + head = head.next; + pivot.next = null; + + Node lessHead = new Node(); // stores the nodes cantaining data less than pivot node + Node lessTail = lessHead; // tail of lessHead + Node greaterHead = new Node(); // stores the nodes cantaining data greater than pivot node + Node greaterTail = greaterHead; // tail of greaterHead + + // Partition the list around the pivot + while (head != null) { + if (head.value < pivot.value) { + lessTail.next = head; + lessTail = lessTail.next; + } else { + greaterTail.next = head; + greaterTail = greaterTail.next; + } + head = head.next; + } + + // Seperating lessHead and greaterHead to form two seperate linkedList + lessTail.next = null; + greaterTail.next = null; + + // Recursively sort the sublists + Node sortedLess = sortList(lessHead.next); + Node sortedGreater = sortList(greaterHead.next); + + // Combine the sorted sublists and pivot + if (sortedLess == null) { + pivot.next = sortedGreater; + return pivot; + } else { + Node current = sortedLess; + while (current.next != null) { + current = current.next; + } + current.next = pivot; + pivot.next = sortedGreater; + return sortedLess; + } + } +} diff --git a/src/test/java/com/thealgorithms/datastructures/lists/QuickSortLinkedListTest.java b/src/test/java/com/thealgorithms/datastructures/lists/QuickSortLinkedListTest.java new file mode 100644 index 000000000000..f4bcfd7fc40d --- /dev/null +++ b/src/test/java/com/thealgorithms/datastructures/lists/QuickSortLinkedListTest.java @@ -0,0 +1,66 @@ +package com.thealgorithms.datastructures.lists; + +/** + * Test cases for QuickSortLinkedList + * Author: Prabhat-Kumar-42 + * GitHub: https://github.com/Prabhat-Kumar-42 + */ + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +public class QuickSortLinkedListTest { + + @Test + public void testSortEmptyList() { + SinglyLinkedList emptyList = new SinglyLinkedList(); + QuickSortLinkedList sorter = new QuickSortLinkedList(emptyList); + + // Test case: Sorting an empty list should result in an empty list + sorter.sortList(); + assertNull(emptyList.getHead()); + } + + @Test + public void testSortSingleNodeList() { + SinglyLinkedList singleNodeList = new SinglyLinkedList(); + singleNodeList.insert(5); + QuickSortLinkedList sorter = new QuickSortLinkedList(singleNodeList); + + // Test case: Sorting a list with a single node should result in the same list + sorter.sortList(); + assertEquals(5, singleNodeList.getHead().value); + assertNull(singleNodeList.getHead().next); + } + + @Test + public void testSortMultipleElementsList() { + SinglyLinkedList list = new SinglyLinkedList(); + list.insert(5); + list.insert(3); + list.insert(8); + list.insert(1); + list.insert(10); + list.insert(2); + list.insert(7); + list.insert(4); + list.insert(9); + list.insert(6); + QuickSortLinkedList sorter = new QuickSortLinkedList(list); + + // Test case: Sorting a list with multiple elements + sorter.sortList(); + assertEquals(1, list.getHead().value); + assertEquals(2, list.getHead().next.value); + assertEquals(3, list.getHead().next.next.value); + assertEquals(4, list.getHead().next.next.next.value); + assertEquals(5, list.getHead().next.next.next.next.value); + assertEquals(6, list.getHead().next.next.next.next.next.value); + assertEquals(7, list.getHead().next.next.next.next.next.next.value); + assertEquals(8, list.getHead().next.next.next.next.next.next.next.value); + assertEquals(9, list.getHead().next.next.next.next.next.next.next.next.value); + assertEquals(10, list.getHead().next.next.next.next.next.next.next.next.next.value); + assertNull(list.getHead().next.next.next.next.next.next.next.next.next.next); + } +}