diff --git a/src/main/java/com/thealgorithms/sorts/BucketSort.java b/src/main/java/com/thealgorithms/sorts/BucketSort.java index 2a48cca0..a6901ac3 100644 --- a/src/main/java/com/thealgorithms/sorts/BucketSort.java +++ b/src/main/java/com/thealgorithms/sorts/BucketSort.java @@ -3,117 +3,128 @@ package com.thealgorithms.sorts; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Random; /** - * Wikipedia: https://en.wikipedia.org/wiki/Bucket_sort + * BucketSort class provides a method to sort an array of elements using the Bucket Sort algorithm + * and implements the SortAlgorithm interface. */ -public final class BucketSort { - private BucketSort() { - } +public class BucketSort implements SortAlgorithm { - public static void main(String[] args) { - int[] arr = new int[10]; + // Constant that defines the divisor for determining the number of buckets + private static final int BUCKET_DIVISOR = 10; - /* generate 10 random numbers from -50 to 49 */ - Random random = new Random(); - for (int i = 0; i < arr.length; ++i) { - arr[i] = random.nextInt(100) - 50; + @Override + public > T[] sort(T[] array) { + if (array.length == 0) { + return array; } - bucketSort(arr); + T min = findMin(array); + T max = findMax(array); + int numberOfBuckets = calculateNumberOfBuckets(array.length); - /* check array is sorted or not */ - for (int i = 0, limit = arr.length - 1; i < limit; ++i) { - assert arr[i] <= arr[i + 1]; - } + List> buckets = initializeBuckets(numberOfBuckets); + distributeElementsIntoBuckets(array, buckets, min, max, numberOfBuckets); + + return concatenateBuckets(buckets, array); } /** - * BucketSort algorithms implements + * Calculates the number of buckets to use based on the size of the array. * - * @param arr the array contains elements + * @param arrayLength the length of the array + * @return the number of buckets */ - public static int[] bucketSort(int[] arr) { - /* get max value of arr */ - int max = max(arr); + private int calculateNumberOfBuckets(final int arrayLength) { + return Math.max(arrayLength / BUCKET_DIVISOR, 1); + } - /* get min value of arr */ - int min = min(arr); - - /* number of buckets */ - int numberOfBuckets = max - min + 1; - - List> buckets = new ArrayList<>(numberOfBuckets); - - /* init buckets */ - for (int i = 0; i < numberOfBuckets; ++i) { + /** + * Initializes a list of empty buckets. + * + * @param numberOfBuckets the number of buckets to initialize + * @param the type of elements to be sorted + * @return a list of empty buckets + */ + private > List> initializeBuckets(int numberOfBuckets) { + List> buckets = new ArrayList<>(numberOfBuckets); + for (int i = 0; i < numberOfBuckets; i++) { buckets.add(new ArrayList<>()); } + return buckets; + } - /* store elements to buckets */ - for (int value : arr) { - int hash = hash(value, min, numberOfBuckets); - buckets.get(hash).add(value); + /** + * Distributes elements from the array into the appropriate buckets. + * + * @param array the array of elements to distribute + * @param buckets the list of buckets + * @param min the minimum value in the array + * @param max the maximum value in the array + * @param numberOfBuckets the total number of buckets + * @param the type of elements in the array + */ + private > void distributeElementsIntoBuckets(T[] array, List> buckets, final T min, final T max, final int numberOfBuckets) { + for (final T element : array) { + int bucketIndex = hash(element, min, max, numberOfBuckets); + buckets.get(bucketIndex).add(element); } + } - /* sort individual bucket */ - for (List bucket : buckets) { - Collections.sort(bucket); - } - - /* concatenate buckets to origin array */ + /** + * Concatenates the sorted buckets back into the original array. + * + * @param buckets the list of sorted buckets + * @param array the original array + * @param the type of elements in the array + * @return the sorted array + */ + private > T[] concatenateBuckets(List> buckets, T[] array) { int index = 0; - for (List bucket : buckets) { - for (int value : bucket) { - arr[index++] = value; + for (List bucket : buckets) { + Collections.sort(bucket); + for (T element : bucket) { + array[index++] = element; } } - - return arr; + return array; } /** - * Get index of bucket which of our elements gets placed into it. + * The method computes the index of the bucket in which a given element should be placed. + * This is done by "normalizing" the element within the range of the array's minimum (min) and maximum (max) values, + * and then mapping this normalized value to a specific bucket index. * - * @param elem the element of array to be sorted - * @param min min value of array - * @param numberOfBucket the number of bucket - * @return index of bucket + * @param element the element of the array + * @param min the minimum value in the array + * @param max the maximum value in the array + * @param numberOfBuckets the total number of buckets + * @param the type of elements in the array + * @return the index of the bucket */ - private static int hash(int elem, int min, int numberOfBucket) { - return (elem - min) / numberOfBucket; + private > int hash(final T element, final T min, final T max, final int numberOfBuckets) { + double range = max.compareTo(min); + double normalizedValue = element.compareTo(min) / range; + return (int) (normalizedValue * (numberOfBuckets - 1)); } - /** - * Calculate max value of array - * - * @param arr the array contains elements - * @return max value of given array - */ - public static int max(int[] arr) { - int max = arr[0]; - for (int value : arr) { - if (value > max) { - max = value; - } - } - return max; - } - - /** - * Calculate min value of array - * - * @param arr the array contains elements - * @return min value of given array - */ - public static int min(int[] arr) { - int min = arr[0]; - for (int value : arr) { - if (value < min) { - min = value; + private > T findMin(T[] array) { + T min = array[0]; + for (T element : array) { + if (element.compareTo(min) < 0) { + min = element; } } return min; } + + private > T findMax(T[] array) { + T max = array[0]; + for (T element : array) { + if (element.compareTo(max) > 0) { + max = element; + } + } + return max; + } } diff --git a/src/test/java/com/thealgorithms/sorts/BucketSortTest.java b/src/test/java/com/thealgorithms/sorts/BucketSortTest.java index bd9d2e3d..a2dcb8ca 100644 --- a/src/test/java/com/thealgorithms/sorts/BucketSortTest.java +++ b/src/test/java/com/thealgorithms/sorts/BucketSortTest.java @@ -1,48 +1,8 @@ package com.thealgorithms.sorts; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; - -import org.junit.jupiter.api.Test; - -public class BucketSortTest { - - @Test - public void bucketSortSingleIntegerArray() { - int[] inputArray = {4}; - int[] outputArray = BucketSort.bucketSort(inputArray); - int[] expectedOutput = {4}; - assertArrayEquals(outputArray, expectedOutput); - } - - @Test - public void bucketSortNonDuplicateIntegerArray() { - int[] inputArray = {6, 1, 99, 27, 15, 23, 36}; - int[] outputArray = BucketSort.bucketSort(inputArray); - int[] expectedOutput = {1, 6, 15, 23, 27, 36, 99}; - assertArrayEquals(outputArray, expectedOutput); - } - - @Test - public void bucketSortDuplicateIntegerArray() { - int[] inputArray = {6, 1, 27, 15, 23, 27, 36, 23}; - int[] outputArray = BucketSort.bucketSort(inputArray); - int[] expectedOutput = {1, 6, 15, 23, 23, 27, 27, 36}; - assertArrayEquals(outputArray, expectedOutput); - } - - @Test - public void bucketSortNonDuplicateIntegerArrayWithNegativeNum() { - int[] inputArray = {6, -1, 99, 27, -15, 23, -36}; - int[] outputArray = BucketSort.bucketSort(inputArray); - int[] expectedOutput = {-36, -15, -1, 6, 23, 27, 99}; - assertArrayEquals(outputArray, expectedOutput); - } - - @Test - public void bucketSortDuplicateIntegerArrayWithNegativeNum() { - int[] inputArray = {6, -1, 27, -15, 23, 27, -36, 23}; - int[] outputArray = BucketSort.bucketSort(inputArray); - int[] expectedOutput = {-36, -15, -1, 6, 23, 23, 27, 27}; - assertArrayEquals(outputArray, expectedOutput); +public class BucketSortTest extends SortingAlgorithmTest { + @Override + SortAlgorithm getSortAlgorithm() { + return new BucketSort(); } }