09 - Bucket Sort
Problem¶
Sort an array by distributing elements into multiple buckets. Each bucket is then sorted individually, either using a different sorting algorithm or by recursively applying bucket sort.
Intuition¶
Imagine you have a large pile of scattered mail. To sort it efficiently, you first put them into boxes based on the city (buckets). Then, you sort the mail within each city's box alphabetically. Finally, you combine the boxes in the order of the cities. Bucket Sort is most efficient when the input is uniformly distributed over a range.
Algorithm Steps¶
- Create \(n\) empty buckets (usually lists).
- For each element \(x\) in the array, insert it into its corresponding bucket (e.g., index = \(n \times x / \text{max\_val}\)).
- Sort each individual bucket using a stable sort (like Insertion Sort).
- Concatenate all sorted buckets into the original array.
Pseudocode¶
procedure bucketSort(A, n)
create n empty buckets B[0..n-1]
for x in A do
idx := index_of_bucket(x)
insert x into B[idx]
for i := 0 to n-1 do
sort(B[i])
concatenate buckets B[0]..B[n-1] into A
end procedure
Java Code using JCF¶
Using a competitive programming structure (TCS NQT Style). This example assumes floating point numbers between 0 and 1, but is adaptable for integers.
import java.util.*;
public class Main {
/**
* Bucket Sort Implementation
*/
public static void bucketSort(List<Float> list) {
int n = list.size();
if (n <= 0) return;
// 1. Create buckets
List<List<Float>> buckets = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
buckets.add(new ArrayList<>());
}
// 2. Put elements in buckets
for (float val : list) {
int bucketIdx = (int) (val * n);
if (bucketIdx >= n) bucketIdx = n - 1; // Safeguard
buckets.get(bucketIdx).add(val);
}
// 3. Sort individual buckets and concatenate
int index = 0;
for (List<Float> bucket : buckets) {
Collections.sort(bucket);
for (float val : bucket) {
list.set(index++, val);
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
if (sc.hasNextInt()) {
int t = sc.nextInt();
while (t-- > 0) {
if (sc.hasNextInt()) {
int n = sc.nextInt();
List<Float> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
if (sc.hasNextFloat()) {
list.add(sc.nextFloat());
}
}
bucketSort(list);
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + (i == list.size() - 1 ? "" : " "));
}
System.out.println();
}
}
}
sc.close();
}
}
Sample Input and Output¶
Input:
Output:
Complexity¶
| Case | Time Complexity | Space Complexity |
|---|---|---|
| Best/Average | \(O(n + k)\) | \(O(n + k)\) |
| Worst Case | \(O(n^2)\) | \(O(n)\) |
- Best/Average: Occurs when elements are uniformly distributed.
- Worst: Occurs when all elements fall into the same bucket (becomes the complexity of the inner sort, e.g., \(O(n \log n)\) or \(O(n^2)\)).
- Stable: Yes (if inner sort is stable).
Variations¶
- Generic Bucket Sort: Handling integers by mapping the range \([min, max]\) to \(n\) buckets.
- Scatter-Gather Sort: Parallel version of bucket sort.
- ProxmapSort: A similar distribution-based sort using a "proximity map".