Feat/tournament sort (#7201)

* feat: implement Smooth Sort algorithm with detailed JavaDoc and test class

* style: format LEONARDO array for improved readability with clang-format

* feat(sorts): add TournamentSort (winner-tree)

* test: add unit test for null array handling in TournamentSort

---------

Co-authored-by: Ahmed Allam <60698204+AllamF5J@users.noreply.github.com>
Co-authored-by: Deniz Altunkapan <deniz.altunkapan@outlook.com>
Co-authored-by: Oleksandr Klymenko <19151554+alxkm@users.noreply.github.com>
This commit is contained in:
Ahmed Allam
2026-01-14 00:04:14 +02:00
committed by GitHub
parent bdda4fa6b4
commit 7148661e44
2 changed files with 103 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
package com.thealgorithms.sorts;
import java.util.Arrays;
/**
* Tournament Sort algorithm implementation.
*
* Tournament sort builds a winner tree (a complete binary tree storing the index
* of the smallest element in each subtree). It then repeatedly extracts the
* winner (minimum) and updates the path from the removed leaf to the root.
*
* Time Complexity:
* - Best case: O(n log n)
* - Average case: O(n log n)
* - Worst case: O(n log n)
*
* Space Complexity: O(n) additional winner-tree storage
*
* @see <a href="https://en.wikipedia.org/wiki/Tournament_sort">Tournament Sort Algorithm</a>
* @see SortAlgorithm
*/
public class TournamentSort implements SortAlgorithm {
@Override
public <T extends Comparable<T>> T[] sort(T[] array) {
if (array == null || array.length < 2) {
return array;
}
final int n = array.length;
final int leafCount = nextPowerOfTwo(n);
// Winner tree represented as an array:
// - Leaves live at [leafCount .. 2*leafCount)
// - Internal nodes live at [1 .. leafCount)
// Each node stores an index into the original array or -1 for "empty".
final int[] tree = new int[2 * leafCount];
Arrays.fill(tree, -1);
for (int i = 0; i < n; i++) {
tree[leafCount + i] = i;
}
for (int node = leafCount - 1; node >= 1; node--) {
tree[node] = winnerIndex(array, tree[node * 2], tree[node * 2 + 1]);
}
final T[] result = array.clone();
for (int out = 0; out < n; out++) {
final int winner = tree[1];
result[out] = array[winner];
int node = leafCount + winner;
tree[node] = -1;
for (node /= 2; node >= 1; node /= 2) {
tree[node] = winnerIndex(array, tree[node * 2], tree[node * 2 + 1]);
}
}
System.arraycopy(result, 0, array, 0, n);
return array;
}
private static int nextPowerOfTwo(int n) {
int power = 1;
while (power < n) {
power <<= 1;
}
return power;
}
private static <T extends Comparable<T>> int winnerIndex(T[] array, int leftIndex, int rightIndex) {
if (leftIndex == -1) {
return rightIndex;
}
if (rightIndex == -1) {
return leftIndex;
}
// If equal, prefer the left element to keep ordering deterministic.
return SortUtils.less(array[rightIndex], array[leftIndex]) ? rightIndex : leftIndex;
}
}

View File

@@ -0,0 +1,19 @@
package com.thealgorithms.sorts;
import static org.junit.jupiter.api.Assertions.assertNull;
import org.junit.jupiter.api.Test;
public class TournamentSortTest extends SortingAlgorithmTest {
@Test
void shouldAcceptWhenNullArrayIsPassed() {
Integer[] array = null;
assertNull(getSortAlgorithm().sort(array));
}
@Override
SortAlgorithm getSortAlgorithm() {
return new TournamentSort();
}
}