|
3 | 3 | import java.util.ArrayList;
|
4 | 4 | import java.util.Collections;
|
5 | 5 | import java.util.List;
|
6 |
| -import java.util.Random; |
7 | 6 |
|
8 | 7 | /**
|
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. |
10 | 10 | */
|
11 |
| -public final class BucketSort { |
12 |
| - private BucketSort() { |
13 |
| - } |
| 11 | +public class BucketSort implements SortAlgorithm { |
14 | 12 |
|
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; |
17 | 15 |
|
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; |
22 | 20 | }
|
23 | 21 |
|
24 |
| - bucketSort(arr); |
| 22 | + T min = findMin(array); |
| 23 | + T max = findMax(array); |
| 24 | + int numberOfBuckets = calculateNumberOfBuckets(array.length); |
25 | 25 |
|
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); |
30 | 30 | }
|
31 | 31 |
|
32 | 32 | /**
|
33 |
| - * BucketSort algorithms implements |
| 33 | + * Calculates the number of buckets to use based on the size of the array. |
34 | 34 | *
|
35 |
| - * @param arr the array contains elements |
| 35 | + * @param arrayLength the length of the array |
| 36 | + * @return the number of buckets |
36 | 37 | */
|
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 | + } |
48 | 41 |
|
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++) { |
51 | 52 | buckets.add(new ArrayList<>());
|
52 | 53 | }
|
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; |
74 | 55 | }
|
75 | 56 |
|
76 | 57 | /**
|
77 |
| - * Get index of bucket which of our elements gets placed into it. |
| 58 | + * Distributes elements from the array into the appropriate buckets. |
78 | 59 | *
|
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 |
83 | 66 | */
|
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 | + } |
86 | 72 | }
|
87 | 73 |
|
88 | 74 | /**
|
89 |
| - * Calculate max value of array |
| 75 | + * Concatenates the sorted buckets back into the original array. |
90 | 76 | *
|
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 |
93 | 81 | */
|
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; |
99 | 88 | }
|
100 | 89 | }
|
101 |
| - return max; |
| 90 | + return array; |
102 | 91 | }
|
103 | 92 |
|
104 | 93 | /**
|
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. |
106 | 97 | *
|
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 |
109 | 104 | */
|
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; |
115 | 116 | }
|
116 | 117 | }
|
117 | 118 | return min;
|
118 | 119 | }
|
| 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 | + } |
119 | 130 | }
|
0 commit comments