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 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 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 = 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
*
- *
> 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);
+ }
+ }
+}