diff --git a/Sorting/src/main/LinkedListMergeSort.java b/Sorting/src/main/LinkedListMergeSort.java new file mode 100644 index 0000000..eda92d0 --- /dev/null +++ b/Sorting/src/main/LinkedListMergeSort.java @@ -0,0 +1,67 @@ +package main; + +public class LinkedListMergeSort { + + public ListNode mergeSortList(ListNode head) { + // Base condition of the recursion. If the list is empty or if only one element is present, + // return the element + if (head == null || head.next == null) { + return head; + } + + // Use slow and fast pointer method. Slow points to the first element and fast points to the + // second element. Then onwards, fast is incremented twice for each increment in slow pointer. + // This way, we can split the linked list in 2 halves. + ListNode slow = head; + ListNode fast = head.next; + while (fast != null) { + fast = fast.next; + if (fast != null) { + slow = slow.next; + fast = fast.next; + } + } + + // Create two lists, slow becomes the head of first half and fast becomes the head of the second + // half. Both halves are passed to the recursion. + fast = slow.next; + slow.next = null; + slow = head; + ListNode h1 = mergeSortList(slow); + ListNode h2 = mergeSortList(fast); + + // Merge the result of sorted lists + ListNode result = merge(h1, h2); + return result; + } + + private ListNode merge(ListNode h1, ListNode h2) { + ListNode p1 = h1; + ListNode p2 = h2; + // Fake head is the previous node of head of the merged linked list. This trick is used when you + // don't want to allocate separate memory for storing the merging result. + ListNode fakeHead = new ListNode(0); + ListNode p = fakeHead; + while (p1 != null && p2 != null) { + if (p1.value <= p2.value) { + p.next = p1; + p1 = p1.next; + } else { + p.next = p2; + p2 = p2.next; + } + p = p.next; + } + if (p1 != null) { + // Attach remaining elements to the result + p.next = p1; + } + if (p2 != null) { + // Attach remaining elements to the result + p.next = p2; + } + // Return fake head's next element which is the actual head of the merged linked list. + return fakeHead.next; + } + +} diff --git a/Sorting/src/main/ListNode.java b/Sorting/src/main/ListNode.java new file mode 100644 index 0000000..366ece0 --- /dev/null +++ b/Sorting/src/main/ListNode.java @@ -0,0 +1,11 @@ +package main; + +public class ListNode { + public final int value; + public ListNode next; + + public ListNode(int value) { + this.value = value; + this.next = null; + } +} diff --git a/Sorting/src/test/LinkedListTest.java b/Sorting/src/test/LinkedListTest.java new file mode 100644 index 0000000..1131d07 --- /dev/null +++ b/Sorting/src/test/LinkedListTest.java @@ -0,0 +1,36 @@ +package test; + +import static org.junit.Assert.fail; +import main.LinkedListMergeSort; +import main.ListNode; + +import org.junit.Before; +import org.junit.Test; + +public class LinkedListTest { + private ListNode n1; + + @Before + public void setup() throws Exception { + n1 = new ListNode(15); + ListNode n2 = new ListNode(2); + ListNode n3 = new ListNode(11); + + n1.next = n2; + n2.next = n3; + n3.next = null; + } + + @Test + public void testLinkedListMergeSort() throws Exception { + LinkedListMergeSort llm = new LinkedListMergeSort(); + ListNode result = llm.mergeSortList(n1); + ListNode temp = result; + while (temp.next != null) { + if (temp.value > temp.next.value) { + fail("LinkedList is not sorted..."); + } + temp = temp.next; + } + } +}