Skip to content

Commit 1977188

Browse files
authored
refactor: cleanup BucketSort (#5314)
1 parent 7a5fe92 commit 1977188

File tree

2 files changed

+91
-120
lines changed

2 files changed

+91
-120
lines changed

src/main/java/com/thealgorithms/sorts/BucketSort.java

+87-76
Original file line numberDiff line numberDiff line change
@@ -3,117 +3,128 @@
33
import java.util.ArrayList;
44
import java.util.Collections;
55
import java.util.List;
6-
import java.util.Random;
76

87
/**
9-
* Wikipedia: https://en.wikipedia.org/wiki/Bucket_sort
8+
* BucketSort class provides a method to sort an array of elements using the Bucket Sort algorithm
9+
* and implements the SortAlgorithm interface.
1010
*/
11-
public final class BucketSort {
12-
private BucketSort() {
13-
}
11+
public class BucketSort implements SortAlgorithm {
1412

15-
public static void main(String[] args) {
16-
int[] arr = new int[10];
13+
// Constant that defines the divisor for determining the number of buckets
14+
private static final int BUCKET_DIVISOR = 10;
1715

18-
/* generate 10 random numbers from -50 to 49 */
19-
Random random = new Random();
20-
for (int i = 0; i < arr.length; ++i) {
21-
arr[i] = random.nextInt(100) - 50;
16+
@Override
17+
public <T extends Comparable<T>> T[] sort(T[] array) {
18+
if (array.length == 0) {
19+
return array;
2220
}
2321

24-
bucketSort(arr);
22+
T min = findMin(array);
23+
T max = findMax(array);
24+
int numberOfBuckets = calculateNumberOfBuckets(array.length);
2525

26-
/* check array is sorted or not */
27-
for (int i = 0, limit = arr.length - 1; i < limit; ++i) {
28-
assert arr[i] <= arr[i + 1];
29-
}
26+
List<List<T>> buckets = initializeBuckets(numberOfBuckets);
27+
distributeElementsIntoBuckets(array, buckets, min, max, numberOfBuckets);
28+
29+
return concatenateBuckets(buckets, array);
3030
}
3131

3232
/**
33-
* BucketSort algorithms implements
33+
* Calculates the number of buckets to use based on the size of the array.
3434
*
35-
* @param arr the array contains elements
35+
* @param arrayLength the length of the array
36+
* @return the number of buckets
3637
*/
37-
public static int[] bucketSort(int[] arr) {
38-
/* get max value of arr */
39-
int max = max(arr);
40-
41-
/* get min value of arr */
42-
int min = min(arr);
43-
44-
/* number of buckets */
45-
int numberOfBuckets = max - min + 1;
46-
47-
List<List<Integer>> buckets = new ArrayList<>(numberOfBuckets);
38+
private int calculateNumberOfBuckets(final int arrayLength) {
39+
return Math.max(arrayLength / BUCKET_DIVISOR, 1);
40+
}
4841

49-
/* init buckets */
50-
for (int i = 0; i < numberOfBuckets; ++i) {
42+
/**
43+
* Initializes a list of empty buckets.
44+
*
45+
* @param numberOfBuckets the number of buckets to initialize
46+
* @param <T> the type of elements to be sorted
47+
* @return a list of empty buckets
48+
*/
49+
private <T extends Comparable<T>> List<List<T>> initializeBuckets(int numberOfBuckets) {
50+
List<List<T>> buckets = new ArrayList<>(numberOfBuckets);
51+
for (int i = 0; i < numberOfBuckets; i++) {
5152
buckets.add(new ArrayList<>());
5253
}
53-
54-
/* store elements to buckets */
55-
for (int value : arr) {
56-
int hash = hash(value, min, numberOfBuckets);
57-
buckets.get(hash).add(value);
58-
}
59-
60-
/* sort individual bucket */
61-
for (List<Integer> bucket : buckets) {
62-
Collections.sort(bucket);
63-
}
64-
65-
/* concatenate buckets to origin array */
66-
int index = 0;
67-
for (List<Integer> bucket : buckets) {
68-
for (int value : bucket) {
69-
arr[index++] = value;
70-
}
71-
}
72-
73-
return arr;
54+
return buckets;
7455
}
7556

7657
/**
77-
* Get index of bucket which of our elements gets placed into it.
58+
* Distributes elements from the array into the appropriate buckets.
7859
*
79-
* @param elem the element of array to be sorted
80-
* @param min min value of array
81-
* @param numberOfBucket the number of bucket
82-
* @return index of bucket
60+
* @param array the array of elements to distribute
61+
* @param buckets the list of buckets
62+
* @param min the minimum value in the array
63+
* @param max the maximum value in the array
64+
* @param numberOfBuckets the total number of buckets
65+
* @param <T> the type of elements in the array
8366
*/
84-
private static int hash(int elem, int min, int numberOfBucket) {
85-
return (elem - min) / numberOfBucket;
67+
private <T extends Comparable<T>> void distributeElementsIntoBuckets(T[] array, List<List<T>> buckets, final T min, final T max, final int numberOfBuckets) {
68+
for (final T element : array) {
69+
int bucketIndex = hash(element, min, max, numberOfBuckets);
70+
buckets.get(bucketIndex).add(element);
71+
}
8672
}
8773

8874
/**
89-
* Calculate max value of array
75+
* Concatenates the sorted buckets back into the original array.
9076
*
91-
* @param arr the array contains elements
92-
* @return max value of given array
77+
* @param buckets the list of sorted buckets
78+
* @param array the original array
79+
* @param <T> the type of elements in the array
80+
* @return the sorted array
9381
*/
94-
public static int max(int[] arr) {
95-
int max = arr[0];
96-
for (int value : arr) {
97-
if (value > max) {
98-
max = value;
82+
private <T extends Comparable<T>> T[] concatenateBuckets(List<List<T>> buckets, T[] array) {
83+
int index = 0;
84+
for (List<T> bucket : buckets) {
85+
Collections.sort(bucket);
86+
for (T element : bucket) {
87+
array[index++] = element;
9988
}
10089
}
101-
return max;
90+
return array;
10291
}
10392

10493
/**
105-
* Calculate min value of array
94+
* The method computes the index of the bucket in which a given element should be placed.
95+
* This is done by "normalizing" the element within the range of the array's minimum (min) and maximum (max) values,
96+
* and then mapping this normalized value to a specific bucket index.
10697
*
107-
* @param arr the array contains elements
108-
* @return min value of given array
98+
* @param element the element of the array
99+
* @param min the minimum value in the array
100+
* @param max the maximum value in the array
101+
* @param numberOfBuckets the total number of buckets
102+
* @param <T> the type of elements in the array
103+
* @return the index of the bucket
109104
*/
110-
public static int min(int[] arr) {
111-
int min = arr[0];
112-
for (int value : arr) {
113-
if (value < min) {
114-
min = value;
105+
private <T extends Comparable<T>> int hash(final T element, final T min, final T max, final int numberOfBuckets) {
106+
double range = max.compareTo(min);
107+
double normalizedValue = element.compareTo(min) / range;
108+
return (int) (normalizedValue * (numberOfBuckets - 1));
109+
}
110+
111+
private <T extends Comparable<T>> T findMin(T[] array) {
112+
T min = array[0];
113+
for (T element : array) {
114+
if (element.compareTo(min) < 0) {
115+
min = element;
115116
}
116117
}
117118
return min;
118119
}
120+
121+
private <T extends Comparable<T>> T findMax(T[] array) {
122+
T max = array[0];
123+
for (T element : array) {
124+
if (element.compareTo(max) > 0) {
125+
max = element;
126+
}
127+
}
128+
return max;
129+
}
119130
}
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,8 @@
11
package com.thealgorithms.sorts;
22

3-
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4-
5-
import org.junit.jupiter.api.Test;
6-
7-
public class BucketSortTest {
8-
9-
@Test
10-
public void bucketSortSingleIntegerArray() {
11-
int[] inputArray = {4};
12-
int[] outputArray = BucketSort.bucketSort(inputArray);
13-
int[] expectedOutput = {4};
14-
assertArrayEquals(outputArray, expectedOutput);
15-
}
16-
17-
@Test
18-
public void bucketSortNonDuplicateIntegerArray() {
19-
int[] inputArray = {6, 1, 99, 27, 15, 23, 36};
20-
int[] outputArray = BucketSort.bucketSort(inputArray);
21-
int[] expectedOutput = {1, 6, 15, 23, 27, 36, 99};
22-
assertArrayEquals(outputArray, expectedOutput);
23-
}
24-
25-
@Test
26-
public void bucketSortDuplicateIntegerArray() {
27-
int[] inputArray = {6, 1, 27, 15, 23, 27, 36, 23};
28-
int[] outputArray = BucketSort.bucketSort(inputArray);
29-
int[] expectedOutput = {1, 6, 15, 23, 23, 27, 27, 36};
30-
assertArrayEquals(outputArray, expectedOutput);
31-
}
32-
33-
@Test
34-
public void bucketSortNonDuplicateIntegerArrayWithNegativeNum() {
35-
int[] inputArray = {6, -1, 99, 27, -15, 23, -36};
36-
int[] outputArray = BucketSort.bucketSort(inputArray);
37-
int[] expectedOutput = {-36, -15, -1, 6, 23, 27, 99};
38-
assertArrayEquals(outputArray, expectedOutput);
39-
}
40-
41-
@Test
42-
public void bucketSortDuplicateIntegerArrayWithNegativeNum() {
43-
int[] inputArray = {6, -1, 27, -15, 23, 27, -36, 23};
44-
int[] outputArray = BucketSort.bucketSort(inputArray);
45-
int[] expectedOutput = {-36, -15, -1, 6, 23, 23, 27, 27};
46-
assertArrayEquals(outputArray, expectedOutput);
3+
public class BucketSortTest extends SortingAlgorithmTest {
4+
@Override
5+
SortAlgorithm getSortAlgorithm() {
6+
return new BucketSort();
477
}
488
}

0 commit comments

Comments
 (0)