Skip to content

Commit fd5905e

Browse files
author
Alex Klymenko
committed
refactor: PigeonholeSort
1 parent 97d416e commit fd5905e

File tree

2 files changed

+107
-35
lines changed

2 files changed

+107
-35
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,88 @@
11
package com.thealgorithms.sorts;
22

33
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.List;
46

57
public class PigeonholeSort {
8+
private PigeonholeSort() {
9+
}
610

7-
/*
8-
This code implements the pigeonhole sort algorithm for the integer array,
9-
but we can also implement this for string arrays too.
10-
See https://www.geeksforgeeks.org/pigeonhole-sort/
11-
*/
12-
void sort(Integer[] array) {
13-
int maxElement = array[0];
14-
for (int element : array) {
15-
if (element > maxElement) {
16-
maxElement = element;
17-
}
11+
/**
12+
* Sorts the given array using the pigeonhole sort algorithm.
13+
*
14+
* @param array the array to be sorted
15+
* @throws IllegalArgumentException if any negative integers are found
16+
* @return the sorted array
17+
*/
18+
public static int[] sort(int[] array) {
19+
if (array.length < 2) {
20+
return array;
1821
}
1922

20-
int numOfPigeonholes = 1 + maxElement;
21-
ArrayList<Integer>[] pigeonHole = new ArrayList[numOfPigeonholes];
23+
checkForNegativeInput(array);
2224

23-
for (int k = 0; k < numOfPigeonholes; k++) {
24-
pigeonHole[k] = new ArrayList<>();
25-
}
25+
final int maxElement = Arrays.stream(array).max().orElseThrow();
26+
final List<List<Integer>> pigeonHoles = createPigeonHoles(maxElement);
2627

27-
for (int t : array) {
28-
pigeonHole[t].add(t);
29-
}
28+
populatePigeonHoles(array, pigeonHoles);
29+
collectFromPigeonHoles(array, pigeonHoles);
30+
31+
return array;
32+
}
3033

31-
int k = 0;
32-
for (ArrayList<Integer> ph : pigeonHole) {
33-
for (int elements : ph) {
34-
array[k] = elements;
35-
k = k + 1;
34+
/**
35+
* Checks if the array contains any negative integers.
36+
*
37+
* @param array the array to be checked
38+
* @throws IllegalArgumentException if any negative integers are found
39+
*/
40+
private static void checkForNegativeInput(int[] array) {
41+
for (int number : array) {
42+
if (number < 0) {
43+
throw new IllegalArgumentException("Array contains non-positive integers.");
3644
}
3745
}
3846
}
3947

40-
public static void main(String[] args) {
41-
PigeonholeSort pigeonholeSort = new PigeonholeSort();
42-
Integer[] arr = {8, 3, 2, 7, 4, 6, 8};
43-
44-
System.out.print("Unsorted order is : ");
45-
SortUtils.print(arr);
48+
/**
49+
* Creates pigeonholes for sorting using an ArrayList of ArrayLists.
50+
*
51+
* @param maxElement the maximum element in the array
52+
* @return an ArrayList of ArrayLists
53+
*/
54+
private static List<List<Integer>> createPigeonHoles(int maxElement) {
55+
List<List<Integer>> pigeonHoles = new ArrayList<>(maxElement + 1);
56+
for (int i = 0; i <= maxElement; i++) {
57+
pigeonHoles.add(new ArrayList<>());
58+
}
59+
return pigeonHoles;
60+
}
4661

47-
pigeonholeSort.sort(arr);
62+
/**
63+
* Populates the pigeonholes with elements from the array.
64+
*
65+
* @param array the array to be sorted
66+
* @param pigeonHoles the pigeonholes to be populated
67+
*/
68+
private static void populatePigeonHoles(int[] array, List<List<Integer>> pigeonHoles) {
69+
for (int element : array) {
70+
pigeonHoles.get(element).add(element);
71+
}
72+
}
4873

49-
System.out.print("Sorted order is : ");
50-
for (int i = 0; i < arr.length; i++) {
51-
assert (arr[i]) <= (arr[i + 1]);
74+
/**
75+
* Collects sorted elements from the pigeonholes back into the array.
76+
*
77+
* @param array the array to be sorted
78+
* @param pigeonHoles the populated pigeonholes
79+
*/
80+
private static void collectFromPigeonHoles(int[] array, List<List<Integer>> pigeonHoles) {
81+
int index = 0;
82+
for (List<Integer> pigeonHole : pigeonHoles) {
83+
for (int element : pigeonHole) {
84+
array[index++] = element;
85+
}
5286
}
53-
SortUtils.print(arr);
5487
}
5588
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.thealgorithms.sorts;
2+
3+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
5+
6+
import java.util.stream.Stream;
7+
import org.junit.jupiter.api.Test;
8+
import org.junit.jupiter.params.ParameterizedTest;
9+
import org.junit.jupiter.params.provider.Arguments;
10+
import org.junit.jupiter.params.provider.MethodSource;
11+
12+
public class PigeonholeSortTest {
13+
14+
@ParameterizedTest
15+
@MethodSource("provideArraysForPigeonholeSort")
16+
public void testPigeonholeSort(int[] inputArray, int[] expectedArray) {
17+
PigeonholeSort.sort(inputArray);
18+
assertArrayEquals(expectedArray, inputArray);
19+
}
20+
21+
private static Stream<Arguments> provideArraysForPigeonholeSort() {
22+
return Stream.of(
23+
Arguments.of(new int[] {}, new int[] {}),
24+
Arguments.of(new int[] {4}, new int[] {4}),
25+
Arguments.of(new int[] {6, 1, 99, 27, 15, 23, 36}, new int[] {1, 6, 15, 23, 27, 36, 99}),
26+
Arguments.of(new int[] {6, 1, 27, 15, 23, 27, 36, 23}, new int[] {1, 6, 15, 23, 23, 27, 27, 36}),
27+
Arguments.of(new int[] {5, 5, 5, 5, 5}, new int[] {5, 5, 5, 5, 5}),
28+
Arguments.of(new int[] {1, 2, 3, 4, 5}, new int[] {1, 2, 3, 4, 5}),
29+
Arguments.of(new int[] {5, 4, 3, 2, 1}, new int[] {1, 2, 3, 4, 5})
30+
);
31+
}
32+
33+
@Test
34+
public void testWithNegativeNumbers() {
35+
assertThrows(IllegalArgumentException.class, () -> {
36+
PigeonholeSort.sort(new int[] {3, 1, 4, 1, 5, -9});
37+
});
38+
}
39+
}

0 commit comments

Comments
 (0)