Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions src/main/java/com/thealgorithms/sorts/TournamentSort.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
19 changes: 19 additions & 0 deletions src/test/java/com/thealgorithms/sorts/TournamentSortTest.java
Original file line number Diff line number Diff line change
@@ -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();
}
}