diff --git a/src/main/java/com/thealgorithms/sorts/TreeSort.java b/src/main/java/com/thealgorithms/sorts/TreeSort.java index 6f4e5509489d..1c0b407c7f84 100644 --- a/src/main/java/com/thealgorithms/sorts/TreeSort.java +++ b/src/main/java/com/thealgorithms/sorts/TreeSort.java @@ -3,6 +3,8 @@ import static com.thealgorithms.sorts.SortUtils.print; import com.thealgorithms.datastructures.trees.BSTRecursiveGeneric; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -30,38 +32,39 @@ public > List sort(List unsortedList) { } private > T[] doTreeSortArray(T[] unsortedArray) { - // create a generic BST tree - BSTRecursiveGeneric tree = new BSTRecursiveGeneric(); - - // add all elements to the tree - for (T element : unsortedArray) { - tree.add(element); - } - - // get the sorted list by inorder traversal of the tree - List sortedList = tree.inorderSort(); - - // add the elements back to the initial array - int i = 0; - for (T element : sortedList) { - unsortedArray[i++] = element; - } - - // return the array - return unsortedArray; + // sort through the list path and copy the result back into the initial array + List sortedList = doTreeSortList(Arrays.asList(unsortedArray)); + return sortedList.toArray(unsortedArray); } private > List doTreeSortList(Iterable unsortedList) { - // create a generic BST tree - BSTRecursiveGeneric tree = new BSTRecursiveGeneric(); + // the BST ignores duplicate keys, so pair every element with its position to keep equal values apart + BSTRecursiveGeneric> tree = new BSTRecursiveGeneric<>(); // add all elements to the tree + int position = 0; for (T element : unsortedList) { - tree.add(element); + tree.add(new Keyed<>(element, position++)); } // get the sorted list by inorder traversal of the tree and return it - return tree.inorderSort(); + List sortedList = new ArrayList<>(); + for (Keyed keyed : tree.inorderSort()) { + sortedList.add(keyed.value()); + } + return sortedList; + } + + /** + * An element plus its original position. Equal elements are ordered by position, + * which also makes the sort stable. + */ + private record Keyed>(T value, int position) implements Comparable> { + @Override + public int compareTo(Keyed other) { + int byValue = value.compareTo(other.value); + return byValue != 0 ? byValue : Integer.compare(position, other.position); + } } public static void main(String[] args) { diff --git a/src/test/java/com/thealgorithms/sorts/TreeSortTest.java b/src/test/java/com/thealgorithms/sorts/TreeSortTest.java index 5fb4c18e953e..6cede929ea51 100644 --- a/src/test/java/com/thealgorithms/sorts/TreeSortTest.java +++ b/src/test/java/com/thealgorithms/sorts/TreeSortTest.java @@ -9,9 +9,20 @@ * @see TreeSort */ -public class TreeSortTest { +public class TreeSortTest extends SortingAlgorithmTest { private TreeSort treeSort = new TreeSort(); + @Override + SortAlgorithm getSortAlgorithm() { + return new TreeSort(); + } + + @Test + public void treeSortKeepsDuplicates() { + Integer[] array = {-1, -1, 0}; + assertArrayEquals(new Integer[] {-1, -1, 0}, treeSort.sort(array)); + } + @Test public void treeSortEmptyArray() { Integer[] inputArray = {};