diff --git a/src/main/java/com/williamfiset/algorithms/graphtheory/ArticulationPointsAdjacencyList.java b/src/main/java/com/williamfiset/algorithms/graphtheory/ArticulationPointsAdjacencyList.java index ea4cf20cf..bd8cc51de 100644 --- a/src/main/java/com/williamfiset/algorithms/graphtheory/ArticulationPointsAdjacencyList.java +++ b/src/main/java/com/williamfiset/algorithms/graphtheory/ArticulationPointsAdjacencyList.java @@ -15,7 +15,7 @@ public class ArticulationPointsAdjacencyList { - private int n, id, rootNodeOutcomingEdgeCount; + private int n, id, rootNodeOutgoingEdgeCount; private boolean solved; private int[] low, ids; private boolean[] visited, isArticulationPoint; @@ -40,9 +40,9 @@ public boolean[] findArticulationPoints() { for (int i = 0; i < n; i++) { if (!visited[i]) { - rootNodeOutcomingEdgeCount = 0; + rootNodeOutgoingEdgeCount = 0; dfs(i, i, -1); - isArticulationPoint[i] = (rootNodeOutcomingEdgeCount > 1); + isArticulationPoint[i] = (rootNodeOutgoingEdgeCount > 1); } } @@ -52,7 +52,7 @@ public boolean[] findArticulationPoints() { private void dfs(int root, int at, int parent) { - if (parent == root) rootNodeOutcomingEdgeCount++; + if (parent == root) rootNodeOutgoingEdgeCount++; visited[at] = true; low[at] = ids[at] = id++; diff --git a/src/main/java/com/williamfiset/algorithms/graphtheory/treealgorithms/LowestCommonAncestorEulerTour.java b/src/main/java/com/williamfiset/algorithms/graphtheory/treealgorithms/LowestCommonAncestorEulerTour.java index 28efcf56f..6fd60fedb 100644 --- a/src/main/java/com/williamfiset/algorithms/graphtheory/treealgorithms/LowestCommonAncestorEulerTour.java +++ b/src/main/java/com/williamfiset/algorithms/graphtheory/treealgorithms/LowestCommonAncestorEulerTour.java @@ -8,10 +8,6 @@ * *

Space Complexity: O(n*log2(n)) * - *

To run script: - * - *

./gradlew run -Palgorithm=graphtheory.treealgorithms.LowestCommonAncestorEulerTour - * * @author William Fiset */ package com.williamfiset.algorithms.graphtheory.treealgorithms; @@ -20,70 +16,6 @@ public class LowestCommonAncestorEulerTour { - public static void main(String[] args) { - TreeNode root = createFirstTreeFromSlides(); - LowestCommonAncestorEulerTour solver = new LowestCommonAncestorEulerTour(root); - - // LCA of 13 and 14 = 2 - TreeNode lca = solver.lca(13, 14); - System.out.printf("LCA of 13 and 14 = %s\n", lca); - if (lca.index() != 2) { - System.out.println("Error, expected lca to be 2"); - } - - // LCA of 9 and 11 = 0 - lca = solver.lca(9, 11); - System.out.printf("LCA of 9 and 11 = %s\n", lca); - if (lca.index() != 0) { - System.out.println("Error, expected lca to be 0"); - } - - // LCA of 12 and 12 = 12 - lca = solver.lca(12, 12); - System.out.printf("LCA of 12 and 12 = %s\n", lca); - if (lca.index() != 12) { - System.out.println("Error, expected lca to be 12"); - } - } - - private static TreeNode createFirstTreeFromSlides() { - int n = 17; - List> tree = createEmptyGraph(n); - - addUndirectedEdge(tree, 0, 1); - addUndirectedEdge(tree, 0, 2); - addUndirectedEdge(tree, 1, 3); - addUndirectedEdge(tree, 1, 4); - addUndirectedEdge(tree, 2, 5); - addUndirectedEdge(tree, 2, 6); - addUndirectedEdge(tree, 2, 7); - addUndirectedEdge(tree, 3, 8); - addUndirectedEdge(tree, 3, 9); - addUndirectedEdge(tree, 5, 10); - addUndirectedEdge(tree, 5, 11); - addUndirectedEdge(tree, 7, 12); - addUndirectedEdge(tree, 7, 13); - addUndirectedEdge(tree, 11, 14); - addUndirectedEdge(tree, 11, 15); - addUndirectedEdge(tree, 11, 16); - - return TreeNode.rootTree(tree, 0); - } - - /* Graph/Tree creation helper methods. */ - - // Create a graph as a adjacency list with 'n' nodes. - public static List> createEmptyGraph(int n) { - List> graph = new ArrayList<>(n); - for (int i = 0; i < n; i++) graph.add(new LinkedList<>()); - return graph; - } - - public static void addUndirectedEdge(List> graph, int from, int to) { - graph.get(from).add(to); - graph.get(to).add(from); - } - public static class TreeNode { // Number of nodes in the subtree. Computed when tree is built. private int n; @@ -100,7 +32,7 @@ public TreeNode(int index) { public TreeNode(int index, TreeNode parent) { this.index = index; this.parent = parent; - children = new LinkedList<>(); + children = new ArrayList<>(); } public void addChildren(TreeNode... nodes) { @@ -134,8 +66,8 @@ public static TreeNode rootTree(List> graph, int rootId) { TreeNode root = new TreeNode(rootId); TreeNode rootedTree = buildTree(graph, root); if (rootedTree.size() < graph.size()) { - System.out.println( - "WARNING: Input graph malformed. Did you forget to include all n-1 edges?"); + throw new IllegalArgumentException( + "Input graph malformed. Did you forget to include all n-1 edges?"); } return rootedTree; } @@ -227,6 +159,20 @@ public TreeNode lca(int index1, int index2) { return nodeOrder[i]; } + /* Graph/Tree creation helper methods. */ + + // Create a graph as an adjacency list with 'n' nodes. + public static List> createEmptyGraph(int n) { + List> graph = new ArrayList<>(n); + for (int i = 0; i < n; i++) graph.add(new ArrayList<>()); + return graph; + } + + public static void addUndirectedEdge(List> graph, int from, int to) { + graph.get(from).add(to); + graph.get(to).add(from); + } + // Sparse table for efficient minimum range queries in O(1) with O(nlogn) space private static class MinSparseTable { @@ -295,4 +241,45 @@ public int queryIndex(int l, int r) { } } } + + public static void main(String[] args) { + TreeNode root = createSampleTree(); + LowestCommonAncestorEulerTour solver = new LowestCommonAncestorEulerTour(root); + + // LCA of 13 and 14 = 2 + TreeNode lca = solver.lca(13, 14); + System.out.printf("LCA of 13 and 14 = %s\n", lca); + + // LCA of 9 and 11 = 0 + lca = solver.lca(9, 11); + System.out.printf("LCA of 9 and 11 = %s\n", lca); + + // LCA of 12 and 12 = 12 + lca = solver.lca(12, 12); + System.out.printf("LCA of 12 and 12 = %s\n", lca); + } + + private static TreeNode createSampleTree() { + int n = 17; + List> tree = createEmptyGraph(n); + + addUndirectedEdge(tree, 0, 1); + addUndirectedEdge(tree, 0, 2); + addUndirectedEdge(tree, 1, 3); + addUndirectedEdge(tree, 1, 4); + addUndirectedEdge(tree, 2, 5); + addUndirectedEdge(tree, 2, 6); + addUndirectedEdge(tree, 2, 7); + addUndirectedEdge(tree, 3, 8); + addUndirectedEdge(tree, 3, 9); + addUndirectedEdge(tree, 5, 10); + addUndirectedEdge(tree, 5, 11); + addUndirectedEdge(tree, 7, 12); + addUndirectedEdge(tree, 7, 13); + addUndirectedEdge(tree, 11, 14); + addUndirectedEdge(tree, 11, 15); + addUndirectedEdge(tree, 11, 16); + + return TreeNode.rootTree(tree, 0); + } } diff --git a/src/main/java/com/williamfiset/algorithms/sorting/BubbleSort.java b/src/main/java/com/williamfiset/algorithms/sorting/BubbleSort.java index b2c512945..158208d44 100644 --- a/src/main/java/com/williamfiset/algorithms/sorting/BubbleSort.java +++ b/src/main/java/com/williamfiset/algorithms/sorting/BubbleSort.java @@ -1,10 +1,6 @@ /** * Bubble sort implementation * - *

Run with: - * - *

$ ./gradlew run -Palgorithm=sorting.BubbleSort - * * @author William Fiset, william.alexandre.fiset@gmail.com */ package com.williamfiset.algorithms.sorting; diff --git a/src/main/java/com/williamfiset/algorithms/sorting/BucketSort.java b/src/main/java/com/williamfiset/algorithms/sorting/BucketSort.java index 5b6f365e4..332dc56f1 100644 --- a/src/main/java/com/williamfiset/algorithms/sorting/BucketSort.java +++ b/src/main/java/com/williamfiset/algorithms/sorting/BucketSort.java @@ -1,10 +1,6 @@ /** * Bucket sort implementation * - *

Run with: - * - *

$ ./gradlew run -Palgorithm=sorting.BucketSort - * * @author William Fiset, william.alexandre.fiset@gmail.com */ package com.williamfiset.algorithms.sorting; @@ -37,7 +33,7 @@ private static void bucketSort(int[] ar, int minValue, int maxValue) { // Place each element in a bucket for (int i = 0; i < N; i++) { - int bi = (ar[i] - minValue) / M; + int bi = (ar[i] - minValue) / N; List bucket = buckets.get(bi); bucket.add(ar[i]); } diff --git a/src/main/java/com/williamfiset/algorithms/sorting/CountingSort.java b/src/main/java/com/williamfiset/algorithms/sorting/CountingSort.java index bf8b8153a..4cbadcb48 100644 --- a/src/main/java/com/williamfiset/algorithms/sorting/CountingSort.java +++ b/src/main/java/com/williamfiset/algorithms/sorting/CountingSort.java @@ -1,10 +1,6 @@ /** * An implementation of counting sort! * - *

Run with: - * - *

$ ./gradlew run -Palgorithm=sorting.CountingSort - * * @author William Fiset, william.alexandre.fiset@gmail.com */ package com.williamfiset.algorithms.sorting; diff --git a/src/main/java/com/williamfiset/algorithms/sorting/Heapsort.java b/src/main/java/com/williamfiset/algorithms/sorting/Heapsort.java index 60bd89858..16265099d 100644 --- a/src/main/java/com/williamfiset/algorithms/sorting/Heapsort.java +++ b/src/main/java/com/williamfiset/algorithms/sorting/Heapsort.java @@ -1,10 +1,6 @@ /** * Implementation of heapsort * - *

Run with: - * - *

$ ./gradlew run -Palgorithm=sorting.Heapsort - * * @author William Fiset, william.alexandre.fiset@gmail.com */ package com.williamfiset.algorithms.sorting; diff --git a/src/main/java/com/williamfiset/algorithms/sorting/InsertionSort.java b/src/main/java/com/williamfiset/algorithms/sorting/InsertionSort.java index 6c4b17535..9a22661e9 100644 --- a/src/main/java/com/williamfiset/algorithms/sorting/InsertionSort.java +++ b/src/main/java/com/williamfiset/algorithms/sorting/InsertionSort.java @@ -1,10 +1,6 @@ /** * Insertion sort implementation * - *

Run with: - * - *

$ ./gradlew run -Palgorithm=sorting.InsertionSort - * * @author William Fiset, william.alexandre.fiset@gmail.com */ package com.williamfiset.algorithms.sorting; diff --git a/src/main/java/com/williamfiset/algorithms/sorting/MergeSort.java b/src/main/java/com/williamfiset/algorithms/sorting/MergeSort.java index 5c290774e..802b3c2fc 100644 --- a/src/main/java/com/williamfiset/algorithms/sorting/MergeSort.java +++ b/src/main/java/com/williamfiset/algorithms/sorting/MergeSort.java @@ -1,10 +1,6 @@ /** * Mergesort implementation * - *

Run with: - * - *

$ ./gradlew run -Palgorithm=sorting.Mergesort - * * @author William Fiset, william.alexandre.fiset@gmail.com */ package com.williamfiset.algorithms.sorting; diff --git a/src/main/java/com/williamfiset/algorithms/sorting/QuickSort.java b/src/main/java/com/williamfiset/algorithms/sorting/QuickSort.java index c799feb1e..1ce672b2d 100644 --- a/src/main/java/com/williamfiset/algorithms/sorting/QuickSort.java +++ b/src/main/java/com/williamfiset/algorithms/sorting/QuickSort.java @@ -1,10 +1,6 @@ /** * Quicksort implementation using Hoare partitioning * - *

Run with: - * - *

$ ./gradlew run -Palgorithm=sorting.QuickSort - * * @author William Fiset, william.alexandre.fiset@gmail.com */ package com.williamfiset.algorithms.sorting; diff --git a/src/main/java/com/williamfiset/algorithms/sorting/QuickSort3.java b/src/main/java/com/williamfiset/algorithms/sorting/QuickSort3.java index 0006d5d38..668c6813b 100644 --- a/src/main/java/com/williamfiset/algorithms/sorting/QuickSort3.java +++ b/src/main/java/com/williamfiset/algorithms/sorting/QuickSort3.java @@ -3,10 +3,6 @@ * improved partitioning algorithm. QuickSort is quite slow in the case where very few unique * elements exist in the array so the QuickSort3 algorithm is used at that time. * - *

Run with: - * - *

$ ./gradlew run -Palgorithm=sorting.QuickSort3 - * * @author Atharva Thorve, aaathorve@gmail.com */ package com.williamfiset.algorithms.sorting; diff --git a/src/main/java/com/williamfiset/algorithms/sorting/RadixSort.java b/src/main/java/com/williamfiset/algorithms/sorting/RadixSort.java index 4e2d5e6b5..f911e9a84 100644 --- a/src/main/java/com/williamfiset/algorithms/sorting/RadixSort.java +++ b/src/main/java/com/williamfiset/algorithms/sorting/RadixSort.java @@ -8,10 +8,6 @@ * *

Time Complexity: O(nw) * - *

Run with: - * - *

$ ./gradlew run -Palgorithm=sorting.RadixSort - * * @author EAlexa */ package com.williamfiset.algorithms.sorting; diff --git a/src/main/java/com/williamfiset/algorithms/sorting/SelectionSort.java b/src/main/java/com/williamfiset/algorithms/sorting/SelectionSort.java index 52d7f60b8..5be22fded 100644 --- a/src/main/java/com/williamfiset/algorithms/sorting/SelectionSort.java +++ b/src/main/java/com/williamfiset/algorithms/sorting/SelectionSort.java @@ -1,10 +1,6 @@ /** * Selection sort implementation * - *

Run with: - * - *

$ ./gradlew run -Palgorithm=sorting.SelectionSort - * * @author William Fiset, william.alexandre.fiset@gmail.com */ package com.williamfiset.algorithms.sorting; diff --git a/src/test/java/com/williamfiset/algorithms/graphtheory/treealgorithms/LowestCommonAncestorEulerTourTest.java b/src/test/java/com/williamfiset/algorithms/graphtheory/treealgorithms/LowestCommonAncestorEulerTourTest.java index f837cb168..879de326f 100644 --- a/src/test/java/com/williamfiset/algorithms/graphtheory/treealgorithms/LowestCommonAncestorEulerTourTest.java +++ b/src/test/java/com/williamfiset/algorithms/graphtheory/treealgorithms/LowestCommonAncestorEulerTourTest.java @@ -1,6 +1,7 @@ package com.williamfiset.algorithms.graphtheory.treealgorithms; import static com.google.common.truth.Truth.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.*; import org.junit.jupiter.api.*; @@ -63,6 +64,123 @@ public void testLcaOfTheSameNodeIsItself() { } } + @Test + public void testLcaIsSymmetric() { + LowestCommonAncestorEulerTour.TreeNode root = createFirstTreeFromSlides(); + LowestCommonAncestorEulerTour solver = new LowestCommonAncestorEulerTour(root); + + // LCA(a, b) should equal LCA(b, a) for all pairs + for (int i = 0; i < root.size(); i++) { + for (int j = i + 1; j < root.size(); j++) { + assertThat(solver.lca(i, j).index()).isEqualTo(solver.lca(j, i).index()); + } + } + } + + @Test + public void testLcaRootIsAlwaysAncestor() { + LowestCommonAncestorEulerTour.TreeNode root = createFirstTreeFromSlides(); + LowestCommonAncestorEulerTour solver = new LowestCommonAncestorEulerTour(root); + + // LCA of root with any node should be root + for (int i = 0; i < root.size(); i++) { + assertThat(solver.lca(0, i).index()).isEqualTo(0); + } + } + + @Test + public void testLcaParentChild() { + LowestCommonAncestorEulerTour.TreeNode root = createFirstTreeFromSlides(); + LowestCommonAncestorEulerTour solver = new LowestCommonAncestorEulerTour(root); + + // LCA of a parent and its direct child is the parent + // Node 1's children are 3 and 4 + assertThat(solver.lca(1, 3).index()).isEqualTo(1); + assertThat(solver.lca(1, 4).index()).isEqualTo(1); + // Node 2's children are 5, 6, 7 + assertThat(solver.lca(2, 5).index()).isEqualTo(2); + assertThat(solver.lca(2, 7).index()).isEqualTo(2); + // Node 11's children are 14, 15, 16 + assertThat(solver.lca(11, 14).index()).isEqualTo(11); + } + + @Test + public void testSingleNodeTree() { + List> tree = LowestCommonAncestorEulerTour.createEmptyGraph(1); + LowestCommonAncestorEulerTour.TreeNode root = + LowestCommonAncestorEulerTour.TreeNode.rootTree(tree, 0); + + LowestCommonAncestorEulerTour solver = new LowestCommonAncestorEulerTour(root); + assertThat(solver.lca(0, 0).index()).isEqualTo(0); + } + + @Test + public void testTwoNodeTree() { + List> tree = LowestCommonAncestorEulerTour.createEmptyGraph(2); + LowestCommonAncestorEulerTour.addUndirectedEdge(tree, 0, 1); + LowestCommonAncestorEulerTour.TreeNode root = + LowestCommonAncestorEulerTour.TreeNode.rootTree(tree, 0); + + LowestCommonAncestorEulerTour solver = new LowestCommonAncestorEulerTour(root); + assertThat(solver.lca(0, 1).index()).isEqualTo(0); + assertThat(solver.lca(1, 0).index()).isEqualTo(0); + assertThat(solver.lca(1, 1).index()).isEqualTo(1); + } + + @Test + public void testLinearChainTree() { + // Build a chain: 0 - 1 - 2 - 3 - 4 + int n = 5; + List> tree = LowestCommonAncestorEulerTour.createEmptyGraph(n); + for (int i = 0; i < n - 1; i++) { + LowestCommonAncestorEulerTour.addUndirectedEdge(tree, i, i + 1); + } + LowestCommonAncestorEulerTour.TreeNode root = + LowestCommonAncestorEulerTour.TreeNode.rootTree(tree, 0); + + LowestCommonAncestorEulerTour solver = new LowestCommonAncestorEulerTour(root); + + // In a chain rooted at 0, LCA of any two nodes is the one closer to root + assertThat(solver.lca(0, 4).index()).isEqualTo(0); + assertThat(solver.lca(1, 4).index()).isEqualTo(1); + assertThat(solver.lca(2, 4).index()).isEqualTo(2); + assertThat(solver.lca(3, 4).index()).isEqualTo(3); + assertThat(solver.lca(1, 3).index()).isEqualTo(1); + } + + @Test + public void testTreeNodeProperties() { + LowestCommonAncestorEulerTour.TreeNode root = createFirstTreeFromSlides(); + + assertThat(root.index()).isEqualTo(0); + assertThat(root.parent()).isNull(); + assertThat(root.size()).isEqualTo(17); + assertThat(root.children()).hasSize(2); + assertThat(root.toString()).isEqualTo("0"); + } + + @Test + public void testTreeNodeChildProperties() { + LowestCommonAncestorEulerTour.TreeNode root = createFirstTreeFromSlides(); + + // Node 1 (first child of root) + LowestCommonAncestorEulerTour.TreeNode node1 = root.children().get(0); + assertThat(node1.index()).isEqualTo(1); + assertThat(node1.parent().index()).isEqualTo(0); + assertThat(node1.children()).hasSize(2); // children: 3, 4 + } + + @Test + public void testMalformedGraphThrows() { + // Graph with 3 nodes but only 1 edge (disconnected) + List> tree = LowestCommonAncestorEulerTour.createEmptyGraph(3); + LowestCommonAncestorEulerTour.addUndirectedEdge(tree, 0, 1); + + assertThrows( + IllegalArgumentException.class, + () -> LowestCommonAncestorEulerTour.TreeNode.rootTree(tree, 0)); + } + @Test public void randomizedLcaQueriesVsOtherImpl() { for (int n = 1; n < 1000; n++) { diff --git a/src/test/java/com/williamfiset/algorithms/sorting/BUILD b/src/test/java/com/williamfiset/algorithms/sorting/BUILD index 484706ad3..51be23a74 100644 --- a/src/test/java/com/williamfiset/algorithms/sorting/BUILD +++ b/src/test/java/com/williamfiset/algorithms/sorting/BUILD @@ -17,6 +17,56 @@ TEST_DEPS = [ "@maven//:com_google_truth_truth", ] + JUNIT5_DEPS +java_test( + name = "BubbleSortTest", + srcs = ["BubbleSortTest.java"], + main_class = "org.junit.platform.console.ConsoleLauncher", + use_testrunner = False, + args = ["--select-class=com.williamfiset.algorithms.sorting.BubbleSortTest"], + runtime_deps = JUNIT5_RUNTIME_DEPS, + deps = TEST_DEPS, +) + +java_test( + name = "CountingSortTest", + srcs = ["CountingSortTest.java"], + main_class = "org.junit.platform.console.ConsoleLauncher", + use_testrunner = False, + args = ["--select-class=com.williamfiset.algorithms.sorting.CountingSortTest"], + runtime_deps = JUNIT5_RUNTIME_DEPS, + deps = TEST_DEPS, +) + +java_test( + name = "HeapsortTest", + srcs = ["HeapsortTest.java"], + main_class = "org.junit.platform.console.ConsoleLauncher", + use_testrunner = False, + args = ["--select-class=com.williamfiset.algorithms.sorting.HeapsortTest"], + runtime_deps = JUNIT5_RUNTIME_DEPS, + deps = TEST_DEPS, +) + +java_test( + name = "InsertionSortTest", + srcs = ["InsertionSortTest.java"], + main_class = "org.junit.platform.console.ConsoleLauncher", + use_testrunner = False, + args = ["--select-class=com.williamfiset.algorithms.sorting.InsertionSortTest"], + runtime_deps = JUNIT5_RUNTIME_DEPS, + deps = TEST_DEPS, +) + +java_test( + name = "MergeSortTest", + srcs = ["MergeSortTest.java"], + main_class = "org.junit.platform.console.ConsoleLauncher", + use_testrunner = False, + args = ["--select-class=com.williamfiset.algorithms.sorting.MergeSortTest"], + runtime_deps = JUNIT5_RUNTIME_DEPS, + deps = TEST_DEPS, +) + java_test( name = "QuickSelectTest", srcs = ["QuickSelectTest.java"], @@ -37,6 +87,46 @@ java_test( deps = TEST_DEPS, ) +java_test( + name = "QuickSortTest", + srcs = ["QuickSortTest.java"], + main_class = "org.junit.platform.console.ConsoleLauncher", + use_testrunner = False, + args = ["--select-class=com.williamfiset.algorithms.sorting.QuickSortTest"], + runtime_deps = JUNIT5_RUNTIME_DEPS, + deps = TEST_DEPS, +) + +java_test( + name = "QuickSort3Test", + srcs = ["QuickSort3Test.java"], + main_class = "org.junit.platform.console.ConsoleLauncher", + use_testrunner = False, + args = ["--select-class=com.williamfiset.algorithms.sorting.QuickSort3Test"], + runtime_deps = JUNIT5_RUNTIME_DEPS, + deps = TEST_DEPS, +) + +java_test( + name = "SelectionSortTest", + srcs = ["SelectionSortTest.java"], + main_class = "org.junit.platform.console.ConsoleLauncher", + use_testrunner = False, + args = ["--select-class=com.williamfiset.algorithms.sorting.SelectionSortTest"], + runtime_deps = JUNIT5_RUNTIME_DEPS, + deps = TEST_DEPS, +) + +java_test( + name = "BucketSortTest", + srcs = ["BucketSortTest.java"], + main_class = "org.junit.platform.console.ConsoleLauncher", + use_testrunner = False, + args = ["--select-class=com.williamfiset.algorithms.sorting.BucketSortTest"], + runtime_deps = JUNIT5_RUNTIME_DEPS, + deps = TEST_DEPS, +) + java_test( name = "SortingTest", srcs = ["SortingTest.java"], diff --git a/src/test/java/com/williamfiset/algorithms/sorting/BubbleSortTest.java b/src/test/java/com/williamfiset/algorithms/sorting/BubbleSortTest.java new file mode 100644 index 000000000..4c6089078 --- /dev/null +++ b/src/test/java/com/williamfiset/algorithms/sorting/BubbleSortTest.java @@ -0,0 +1,86 @@ +package com.williamfiset.algorithms.sorting; + +import static com.google.common.truth.Truth.assertThat; + +import com.williamfiset.algorithms.utils.TestUtils; +import java.util.Arrays; +import org.junit.jupiter.api.*; + +public class BubbleSortTest { + + private final BubbleSort sorter = new BubbleSort(); + + @Test + public void testEmptyArray() { + int[] array = {}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {}); + } + + @Test + public void testSingleElement() { + int[] array = {7}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {7}); + } + + @Test + public void testAlreadySorted() { + int[] array = {1, 2, 3, 4, 5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testReverseSorted() { + int[] array = {5, 4, 3, 2, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testWithDuplicates() { + int[] array = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 1, 2, 3, 3, 4, 5, 5, 6, 9}); + } + + @Test + public void testAllSameElements() { + int[] array = {5, 5, 5, 5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {5, 5, 5, 5}); + } + + @Test + public void testNegativeNumbers() { + int[] array = {-3, -1, -4, -1, -5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -4, -3, -1, -1}); + } + + @Test + public void testMixedPositiveAndNegative() { + int[] array = {3, -2, 0, 7, -5, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -2, 0, 1, 3, 7}); + } + + @Test + public void testTwoElements() { + int[] array = {9, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 9}); + } + + @Test + public void testRandomized() { + for (int size = 0; size < 200; size++) { + int[] values = TestUtils.randomIntegerArray(size, -50, 51); + int[] expected = values.clone(); + Arrays.sort(expected); + sorter.sort(values); + assertThat(values).isEqualTo(expected); + } + } +} diff --git a/src/test/java/com/williamfiset/algorithms/sorting/BucketSortTest.java b/src/test/java/com/williamfiset/algorithms/sorting/BucketSortTest.java new file mode 100644 index 000000000..37259180a --- /dev/null +++ b/src/test/java/com/williamfiset/algorithms/sorting/BucketSortTest.java @@ -0,0 +1,131 @@ +package com.williamfiset.algorithms.sorting; + +import static com.google.common.truth.Truth.assertThat; + +import com.williamfiset.algorithms.utils.TestUtils; +import java.util.Arrays; +import org.junit.jupiter.api.*; + +public class BucketSortTest { + + private final BucketSort sorter = new BucketSort(); + + @Test + public void testEmptyArray() { + int[] array = {}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {}); + } + + @Test + public void testSingleElement() { + int[] array = {42}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {42}); + } + + @Test + public void testAllSameElements() { + int[] array = {5, 5, 5, 5, 5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {5, 5, 5, 5, 5}); + } + + @Test + public void testAlreadySorted() { + int[] array = {1, 2, 3, 4, 5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testReverseSorted() { + int[] array = {5, 4, 3, 2, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testWithDuplicates() { + int[] array = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 1, 2, 3, 3, 4, 5, 5, 6, 9}); + } + + @Test + public void testNegativeNumbers() { + int[] array = {-3, -1, -4, -1, -5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -4, -3, -1, -1}); + } + + @Test + public void testMixedPositiveAndNegative() { + int[] array = {3, -2, 0, 7, -5, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -2, 0, 1, 3, 7}); + } + + @Test + public void testTwoElements() { + int[] array = {9, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 9}); + } + + @Test + public void testLargeRange() { + int[] array = {1000, 1, 500, 250, 750}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 250, 500, 750, 1000}); + } + + @Test + public void testRangeGreaterThanN() { + // Range (M) much larger than number of elements (N) to exercise multiple buckets + int[] array = {100, 1, 50, 99, 2}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 50, 99, 100}); + } + + @Test + public void testRangeSmallerThanN() { + // Range (M) smaller than number of elements (N), most elements share a bucket + int[] array = {3, 1, 2, 1, 3, 2, 1, 3, 2, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 1, 1, 1, 2, 2, 2, 3, 3, 3}); + } + + @Test + public void testRandomizedSmall() { + for (int size = 0; size < 500; size++) { + int[] values = TestUtils.randomIntegerArray(size, 0, 51); + int[] expected = values.clone(); + Arrays.sort(expected); + sorter.sort(values); + assertThat(values).isEqualTo(expected); + } + } + + @Test + public void testRandomizedWithNegatives() { + for (int size = 1; size < 500; size++) { + int[] values = TestUtils.randomIntegerArray(size, -50, 51); + int[] expected = values.clone(); + Arrays.sort(expected); + sorter.sort(values); + assertThat(values).isEqualTo(expected); + } + } + + @Test + public void testRandomizedLargeRange() { + for (int size = 1; size < 200; size++) { + int[] values = TestUtils.randomIntegerArray(size, -10000, 10001); + int[] expected = values.clone(); + Arrays.sort(expected); + sorter.sort(values); + assertThat(values).isEqualTo(expected); + } + } +} diff --git a/src/test/java/com/williamfiset/algorithms/sorting/CountingSortTest.java b/src/test/java/com/williamfiset/algorithms/sorting/CountingSortTest.java new file mode 100644 index 000000000..82bad7f84 --- /dev/null +++ b/src/test/java/com/williamfiset/algorithms/sorting/CountingSortTest.java @@ -0,0 +1,86 @@ +package com.williamfiset.algorithms.sorting; + +import static com.google.common.truth.Truth.assertThat; + +import com.williamfiset.algorithms.utils.TestUtils; +import java.util.Arrays; +import org.junit.jupiter.api.*; + +public class CountingSortTest { + + private final CountingSort sorter = new CountingSort(); + + @Test + public void testEmptyArray() { + int[] array = {}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {}); + } + + @Test + public void testSingleElement() { + int[] array = {42}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {42}); + } + + @Test + public void testAlreadySorted() { + int[] array = {1, 2, 3, 4, 5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testReverseSorted() { + int[] array = {5, 4, 3, 2, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testWithDuplicates() { + int[] array = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 1, 2, 3, 3, 4, 5, 5, 6, 9}); + } + + @Test + public void testAllSameElements() { + int[] array = {7, 7, 7, 7}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {7, 7, 7, 7}); + } + + @Test + public void testNegativeNumbers() { + int[] array = {-3, -1, -4, -1, -5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -4, -3, -1, -1}); + } + + @Test + public void testMixedPositiveAndNegative() { + int[] array = {4, -10, 0, 6, 1, -5, -5, 1, 1, -2, 0, 6, 8, -7, 10}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-10, -7, -5, -5, -2, 0, 0, 1, 1, 1, 4, 6, 6, 8, 10}); + } + + @Test + public void testTwoElements() { + int[] array = {9, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 9}); + } + + @Test + public void testRandomized() { + for (int size = 0; size < 500; size++) { + int[] values = TestUtils.randomIntegerArray(size, -50, 51); + int[] expected = values.clone(); + Arrays.sort(expected); + sorter.sort(values); + assertThat(values).isEqualTo(expected); + } + } +} diff --git a/src/test/java/com/williamfiset/algorithms/sorting/HeapsortTest.java b/src/test/java/com/williamfiset/algorithms/sorting/HeapsortTest.java new file mode 100644 index 000000000..2028e84d5 --- /dev/null +++ b/src/test/java/com/williamfiset/algorithms/sorting/HeapsortTest.java @@ -0,0 +1,86 @@ +package com.williamfiset.algorithms.sorting; + +import static com.google.common.truth.Truth.assertThat; + +import com.williamfiset.algorithms.utils.TestUtils; +import java.util.Arrays; +import org.junit.jupiter.api.*; + +public class HeapsortTest { + + private final Heapsort sorter = new Heapsort(); + + @Test + public void testEmptyArray() { + int[] array = {}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {}); + } + + @Test + public void testSingleElement() { + int[] array = {42}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {42}); + } + + @Test + public void testAlreadySorted() { + int[] array = {1, 2, 3, 4, 5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testReverseSorted() { + int[] array = {5, 4, 3, 2, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testWithDuplicates() { + int[] array = {10, 4, 6, 4, 8, -13, 2, 3}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-13, 2, 3, 4, 4, 6, 8, 10}); + } + + @Test + public void testAllSameElements() { + int[] array = {3, 3, 3, 3, 3}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {3, 3, 3, 3, 3}); + } + + @Test + public void testNegativeNumbers() { + int[] array = {-3, -1, -4, -1, -5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -4, -3, -1, -1}); + } + + @Test + public void testMixedPositiveAndNegative() { + int[] array = {3, -2, 0, 7, -5, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -2, 0, 1, 3, 7}); + } + + @Test + public void testTwoElements() { + int[] array = {9, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 9}); + } + + @Test + public void testRandomized() { + for (int size = 0; size < 500; size++) { + int[] values = TestUtils.randomIntegerArray(size, -50, 51); + int[] expected = values.clone(); + Arrays.sort(expected); + sorter.sort(values); + assertThat(values).isEqualTo(expected); + } + } +} diff --git a/src/test/java/com/williamfiset/algorithms/sorting/InsertionSortTest.java b/src/test/java/com/williamfiset/algorithms/sorting/InsertionSortTest.java new file mode 100644 index 000000000..0f4e8d243 --- /dev/null +++ b/src/test/java/com/williamfiset/algorithms/sorting/InsertionSortTest.java @@ -0,0 +1,86 @@ +package com.williamfiset.algorithms.sorting; + +import static com.google.common.truth.Truth.assertThat; + +import com.williamfiset.algorithms.utils.TestUtils; +import java.util.Arrays; +import org.junit.jupiter.api.*; + +public class InsertionSortTest { + + private final InsertionSort sorter = new InsertionSort(); + + @Test + public void testEmptyArray() { + int[] array = {}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {}); + } + + @Test + public void testSingleElement() { + int[] array = {42}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {42}); + } + + @Test + public void testAlreadySorted() { + int[] array = {1, 2, 3, 4, 5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testReverseSorted() { + int[] array = {5, 4, 3, 2, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testWithDuplicates() { + int[] array = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 1, 2, 3, 3, 4, 5, 5, 6, 9}); + } + + @Test + public void testAllSameElements() { + int[] array = {4, 4, 4, 4}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {4, 4, 4, 4}); + } + + @Test + public void testNegativeNumbers() { + int[] array = {-3, -1, -4, -1, -5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -4, -3, -1, -1}); + } + + @Test + public void testMixedPositiveAndNegative() { + int[] array = {3, -2, 0, 7, -5, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -2, 0, 1, 3, 7}); + } + + @Test + public void testTwoElements() { + int[] array = {9, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 9}); + } + + @Test + public void testRandomized() { + for (int size = 0; size < 200; size++) { + int[] values = TestUtils.randomIntegerArray(size, -50, 51); + int[] expected = values.clone(); + Arrays.sort(expected); + sorter.sort(values); + assertThat(values).isEqualTo(expected); + } + } +} diff --git a/src/test/java/com/williamfiset/algorithms/sorting/MergeSortTest.java b/src/test/java/com/williamfiset/algorithms/sorting/MergeSortTest.java new file mode 100644 index 000000000..ed8590849 --- /dev/null +++ b/src/test/java/com/williamfiset/algorithms/sorting/MergeSortTest.java @@ -0,0 +1,93 @@ +package com.williamfiset.algorithms.sorting; + +import static com.google.common.truth.Truth.assertThat; + +import com.williamfiset.algorithms.utils.TestUtils; +import java.util.Arrays; +import org.junit.jupiter.api.*; + +public class MergeSortTest { + + private final MergeSort sorter = new MergeSort(); + + @Test + public void testEmptyArray() { + int[] array = {}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {}); + } + + @Test + public void testSingleElement() { + int[] array = {42}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {42}); + } + + @Test + public void testAlreadySorted() { + int[] array = {1, 2, 3, 4, 5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testReverseSorted() { + int[] array = {5, 4, 3, 2, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testWithDuplicates() { + int[] array = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 1, 2, 3, 3, 4, 5, 5, 6, 9}); + } + + @Test + public void testAllSameElements() { + int[] array = {6, 6, 6, 6}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {6, 6, 6, 6}); + } + + @Test + public void testNegativeNumbers() { + int[] array = {-3, -1, -4, -1, -5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -4, -3, -1, -1}); + } + + @Test + public void testMixedPositiveAndNegative() { + int[] array = {3, -2, 0, 7, -5, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -2, 0, 1, 3, 7}); + } + + @Test + public void testTwoElements() { + int[] array = {9, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 9}); + } + + @Test + public void testStaticMergesortMethod() { + int[] array = {10, 4, 6, 4, 8, -13, 2, 3}; + int[] result = MergeSort.mergesort(array); + assertThat(result).isEqualTo(new int[] {-13, 2, 3, 4, 4, 6, 8, 10}); + } + + @Test + public void testRandomized() { + for (int size = 0; size < 500; size++) { + int[] values = TestUtils.randomIntegerArray(size, -50, 51); + int[] expected = values.clone(); + Arrays.sort(expected); + sorter.sort(values); + assertThat(values).isEqualTo(expected); + } + } +} diff --git a/src/test/java/com/williamfiset/algorithms/sorting/QuickSort3Test.java b/src/test/java/com/williamfiset/algorithms/sorting/QuickSort3Test.java new file mode 100644 index 000000000..3b9302e65 --- /dev/null +++ b/src/test/java/com/williamfiset/algorithms/sorting/QuickSort3Test.java @@ -0,0 +1,94 @@ +package com.williamfiset.algorithms.sorting; + +import static com.google.common.truth.Truth.assertThat; + +import com.williamfiset.algorithms.utils.TestUtils; +import java.util.Arrays; +import org.junit.jupiter.api.*; + +public class QuickSort3Test { + + private final QuickSort3 sorter = new QuickSort3(); + + @Test + public void testEmptyArray() { + int[] array = {}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {}); + } + + @Test + public void testSingleElement() { + int[] array = {42}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {42}); + } + + @Test + public void testAlreadySorted() { + int[] array = {1, 2, 3, 4, 5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testReverseSorted() { + int[] array = {5, 4, 3, 2, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testWithDuplicates() { + int[] array = {10, 4, 6, 4, 8, -13, 2, 3}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-13, 2, 3, 4, 4, 6, 8, 10}); + } + + @Test + public void testAllSameElements() { + int[] array = {5, 5, 5, 5, 5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {5, 5, 5, 5, 5}); + } + + @Test + public void testManyDuplicates() { + // QuickSort3 is specifically optimized for arrays with few unique elements + int[] array = {2, 1, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3}); + } + + @Test + public void testNegativeNumbers() { + int[] array = {-3, -1, -4, -1, -5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -4, -3, -1, -1}); + } + + @Test + public void testMixedPositiveAndNegative() { + int[] array = {3, -2, 0, 7, -5, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -2, 0, 1, 3, 7}); + } + + @Test + public void testTwoElements() { + int[] array = {9, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 9}); + } + + @Test + public void testRandomized() { + for (int size = 0; size < 500; size++) { + int[] values = TestUtils.randomIntegerArray(size, -50, 51); + int[] expected = values.clone(); + Arrays.sort(expected); + sorter.sort(values); + assertThat(values).isEqualTo(expected); + } + } +} diff --git a/src/test/java/com/williamfiset/algorithms/sorting/QuickSortTest.java b/src/test/java/com/williamfiset/algorithms/sorting/QuickSortTest.java new file mode 100644 index 000000000..76d612c1c --- /dev/null +++ b/src/test/java/com/williamfiset/algorithms/sorting/QuickSortTest.java @@ -0,0 +1,86 @@ +package com.williamfiset.algorithms.sorting; + +import static com.google.common.truth.Truth.assertThat; + +import com.williamfiset.algorithms.utils.TestUtils; +import java.util.Arrays; +import org.junit.jupiter.api.*; + +public class QuickSortTest { + + private final QuickSort sorter = new QuickSort(); + + @Test + public void testEmptyArray() { + int[] array = {}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {}); + } + + @Test + public void testSingleElement() { + int[] array = {42}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {42}); + } + + @Test + public void testAlreadySorted() { + int[] array = {1, 2, 3, 4, 5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testReverseSorted() { + int[] array = {5, 4, 3, 2, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testWithDuplicates() { + int[] array = {10, 4, 6, 4, 8, -13, 2, 3}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-13, 2, 3, 4, 4, 6, 8, 10}); + } + + @Test + public void testAllSameElements() { + int[] array = {5, 5, 5, 5, 5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {5, 5, 5, 5, 5}); + } + + @Test + public void testNegativeNumbers() { + int[] array = {-3, -1, -4, -1, -5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -4, -3, -1, -1}); + } + + @Test + public void testMixedPositiveAndNegative() { + int[] array = {3, -2, 0, 7, -5, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -2, 0, 1, 3, 7}); + } + + @Test + public void testTwoElements() { + int[] array = {9, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 9}); + } + + @Test + public void testRandomized() { + for (int size = 0; size < 500; size++) { + int[] values = TestUtils.randomIntegerArray(size, -50, 51); + int[] expected = values.clone(); + Arrays.sort(expected); + sorter.sort(values); + assertThat(values).isEqualTo(expected); + } + } +} diff --git a/src/test/java/com/williamfiset/algorithms/sorting/SelectionSortTest.java b/src/test/java/com/williamfiset/algorithms/sorting/SelectionSortTest.java new file mode 100644 index 000000000..33362a7b5 --- /dev/null +++ b/src/test/java/com/williamfiset/algorithms/sorting/SelectionSortTest.java @@ -0,0 +1,86 @@ +package com.williamfiset.algorithms.sorting; + +import static com.google.common.truth.Truth.assertThat; + +import com.williamfiset.algorithms.utils.TestUtils; +import java.util.Arrays; +import org.junit.jupiter.api.*; + +public class SelectionSortTest { + + private final SelectionSort sorter = new SelectionSort(); + + @Test + public void testEmptyArray() { + int[] array = {}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {}); + } + + @Test + public void testSingleElement() { + int[] array = {42}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {42}); + } + + @Test + public void testAlreadySorted() { + int[] array = {1, 2, 3, 4, 5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testReverseSorted() { + int[] array = {5, 4, 3, 2, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 2, 3, 4, 5}); + } + + @Test + public void testWithDuplicates() { + int[] array = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 1, 2, 3, 3, 4, 5, 5, 6, 9}); + } + + @Test + public void testAllSameElements() { + int[] array = {8, 8, 8, 8}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {8, 8, 8, 8}); + } + + @Test + public void testNegativeNumbers() { + int[] array = {-3, -1, -4, -1, -5}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -4, -3, -1, -1}); + } + + @Test + public void testMixedPositiveAndNegative() { + int[] array = {3, -2, 0, 7, -5, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {-5, -2, 0, 1, 3, 7}); + } + + @Test + public void testTwoElements() { + int[] array = {9, 1}; + sorter.sort(array); + assertThat(array).isEqualTo(new int[] {1, 9}); + } + + @Test + public void testRandomized() { + for (int size = 0; size < 200; size++) { + int[] values = TestUtils.randomIntegerArray(size, -50, 51); + int[] expected = values.clone(); + Arrays.sort(expected); + sorter.sort(values); + assertThat(values).isEqualTo(expected); + } + } +}