diff --git a/DIRECTORY.md b/DIRECTORY.md index 0c14970b..7e726f31 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -511,6 +511,7 @@ * [MergeSortRecursive](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/MergeSortRecursive.java) * [OddEvenSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/OddEvenSort.java) * [PancakeSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/PancakeSort.java) + * [PatienceSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/PatienceSort.java) * [PigeonholeSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/PigeonholeSort.java) * [QuickSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/QuickSort.java) * [RadixSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/RadixSort.java) @@ -881,6 +882,7 @@ * [MergeSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/MergeSortTest.java) * [OddEvenSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/OddEvenSortTest.java) * [PancakeSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/PancakeSortTest.java) + * [PatienceSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/PatienceSortTest.java) * [QuickSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/QuickSortTest.java) * [RadixSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/RadixSortTest.java) * [SelectionSortRecursiveTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/SelectionSortRecursiveTest.java) diff --git a/src/main/java/com/thealgorithms/sorts/PatienceSort.java b/src/main/java/com/thealgorithms/sorts/PatienceSort.java new file mode 100644 index 00000000..52ed30d5 --- /dev/null +++ b/src/main/java/com/thealgorithms/sorts/PatienceSort.java @@ -0,0 +1,112 @@ +package com.thealgorithms.sorts; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.PriorityQueue; + +/** + * This class implements the Patience Sort algorithm. Patience Sort is a sorting algorithm that + * is particularly good for sorting sequences that are already partially sorted. + */ +public class PatienceSort implements SortAlgorithm { + + /** + * Sorts an array of comparable elements using the Patience Sort algorithm. + * + * @param array the array to be sorted + * @param the type of elements in the array, must be comparable + * @return the sorted array + */ + @Override + public > T[] sort(T[] array) { + if (array.length == 0) { + return array; + } + + final List> piles = formPiles(array); + final PriorityQueue> pq = mergePiles(piles); + extractPiles(array, pq); + + return array; + } + + /** + * Forms piles from the given array. Each pile is a list of elements where + * each element is smaller than the one before it. Binary search is used + * to find the appropriate pile for each element. + * + * @param array the array of elements to be organized into piles + * @param the type of elements in the array, must be comparable + * @return a list of piles + */ + private static > List> formPiles(final T[] array) { + final List> piles = new ArrayList<>(); + final List lastElements = new ArrayList<>(); + + for (T x : array) { + int pos = Collections.binarySearch(lastElements, x); + if (pos < 0) { + pos = -pos - 1; + } + + if (pos < piles.size()) { + piles.get(pos).add(x); + lastElements.set(pos, x); + } else { + List newPile = new ArrayList<>(); + newPile.add(x); + piles.add(newPile); + lastElements.add(x); + } + } + + return piles; + } + + /** + * Merges the piles into a priority queue where the smallest elements are + * prioritized. + * + * @param piles the list of piles to be merged + * @param the type of elements in the piles, must be comparable + * @return a priority queue containing the top element of each pile + */ + private static > PriorityQueue> mergePiles(final List> piles) { + PriorityQueue> pq = new PriorityQueue<>(); + for (List pile : piles) { + pq.add(new PileNode<>(pile.removeLast(), pile)); + } + return pq; + } + + /** + * Extracts elements from the priority queue to form the sorted array. + * + * @param array the array to be filled with sorted elements + * @param pq the priority queue containing the elements to be extracted + * @param the type of elements in the array, must be comparable + */ + private static > void extractPiles(final T[] array, final PriorityQueue> pq) { + int index = 0; + while (!pq.isEmpty()) { + PileNode node = pq.poll(); + array[index++] = node.value; + if (!node.pile.isEmpty()) { + pq.add(new PileNode<>(node.pile.removeLast(), node.pile)); + } + } + } + + /** + * A helper record representing a node in the priority queue. + * + * @param the type of elements in the node, must be comparable + */ + private record PileNode>(T value, List pile) implements Comparable> { + @Override + public int compareTo(PileNode other) { + return this.value.compareTo(other.value); + } + } +} diff --git a/src/test/java/com/thealgorithms/sorts/PatienceSortTest.java b/src/test/java/com/thealgorithms/sorts/PatienceSortTest.java new file mode 100644 index 00000000..f3cf7874 --- /dev/null +++ b/src/test/java/com/thealgorithms/sorts/PatienceSortTest.java @@ -0,0 +1,8 @@ +package com.thealgorithms.sorts; + +public class PatienceSortTest extends SortingAlgorithmTest { + @Override + SortAlgorithm getSortAlgorithm() { + return new PatienceSort(); + } +}