How it works
Distributes elements into buckets, sorts each bucket individually (usually with insertion sort), then concatenates.
Implementation
function bucketSort(arr, stats) { const n = arr.length; if (n < 2) { if (n === 1) markSorted(0); return; } let min = arr[0]; let max = arr[0]; for (let i = 1; i < n; i++) { if (arr[i] < min) min = arr[i]; if (arr[i] > max) max = arr[i]; } const metrics = stats.educational.metrics; const recordMetric = (name, delta = 1) => { metrics[name] = (metrics[name] || 0) + delta; }; if (min === max) { for (let i = 0; i < n; i++) markSorted(i); checkpoint(n, n); return; } const bucketCount = n; const range = max - min; const buckets = Array.from({ length: bucketCount }, () => []); metrics.bucketCount = bucketCount; for (let i = 0; i < n; i++) { const normalized = (arr[i] - min) / range; const bucketIndex = Math.min(bucketCount - 1, Math.floor(normalized * (bucketCount - 1))); buckets[bucketIndex].push(arr[i]); recordMetric('bucketAssignments'); recordMetric('distributionReads'); } function sortBucket(bucket) { recordMetric('bucketSortCalls'); for (let i = 1; i < bucket.length; i++) { const value = bucket[i]; let j = i; while (j > 0) { if (bucket[j - 1] <= value) break; bucket[j] = bucket[j - 1]; j--; recordMetric('bucketShifts'); } bucket[j] = value; } } let write = 0; for (let bucketIndex = 0; bucketIndex < bucketCount; bucketIndex++) { const bucket = buckets[bucketIndex]; if (bucket.length > 1) sortBucket(bucket); for (let i = 0; i < bucket.length; i++) { arr[write] = bucket[i]; recordMetric('outputWrites'); write(write, arr[write]); markSorted(write); write++; } checkpoint(write, n); } }
def bucketSort(arr, stats): def recordMetric(name, ): metrics[name] = ((metrics[name] or 0) + delta) def sortBucket(bucket): recordMetric("bucketSortCalls") for i in range(1, len(bucket)): value = bucket[i] j = i while (j > 0): if (bucket[(j - 1)] <= value): break bucket[j] = bucket[(j - 1)] j -= 1 recordMetric("bucketShifts") bucket[j] = value if (n < 2): if (n == 1): markSorted(0) return min = arr[0] max = arr[0] for i in range(1, n): if (arr[i] < min): min = arr[i] if (arr[i] > max): max = arr[i] if (min == max): for i in range(n): markSorted(i) checkpoint(n, n) return bucketCount = n range = (max - min) buckets = [[] for _ in range(bucketCount)] metrics.bucketCount = bucketCount for i in range(n): normalized = ((arr[i] - min) / range) bucketIndex = ((bucketCount - 1) if (bucketCount - 1) <= int((normalized * (bucketCount - 1))) else int((normalized * (bucketCount - 1)))) buckets[bucketIndex].append(arr[i]) recordMetric("bucketAssignments") recordMetric("distributionReads") write = 0 for bucketIndex in range(bucketCount): bucket = buckets[bucketIndex] if (len(bucket) > 1): sortBucket(bucket) for i in range(len(bucket)): arr[write] = bucket[i] recordMetric("outputWrites") write(write, arr[write]) markSorted(write) write += 1 checkpoint(write, n)
#include <vector> #include <algorithm> #include <cmath> void recordMetric(int name, int ); void sortBucket(int bucket); void recordMetric(int name, int ) { metrics[name] = (((metrics[name]) != 0 ? (metrics[name]) : (0)) + delta); } void sortBucket(int bucket) { recordMetric("bucketSortCalls"); for(int i=1; i<n; i++) { int value = bucket[i]; int j = i; while((j > 0)) { if((bucket[(j - 1)] <= value)) { break; } bucket[j] = bucket[(j - 1)]; j--; recordMetric("bucketShifts"); } bucket[j] = value; } } void sort(std::vector<int>& arr, int n, int& comparisons, int& swaps) { if((n < 2)) { if((n == 1)) { markSorted(0); } return; } int min = arr[0]; int max = arr[0]; for(int i=1; i<n; i++) { if((arr[i] < min)) { min = arr[i]; } if((arr[i] > max)) { max = arr[i]; } } int metrics = educational.metrics; if((min == max)) { for(int i=0; i<n; i++) { markSorted(i); } checkpoint(n, n); return; } int bucketCount = n; int range = (max - min); std::vector<int> buckets(bucketCount); for(int _mi=0;_mi<bucketCount;_mi++) buckets[_mi]=_mi; metrics.bucketCount = bucketCount; for(int i=0; i<n; i++) { int normalized = ((arr[i] - min) / range); int bucketIndex = (((bucketCount - 1)) < ((int)std::floor((normalized * (bucketCount - 1)))) ? ((bucketCount - 1)) : ((int)std::floor((normalized * (bucketCount - 1))))); buckets[bucketIndex].push_back(arr[i]); recordMetric("bucketAssignments"); recordMetric("distributionReads"); } int write = 0; for(int bucketIndex=0; bucketIndex<bucketCount; bucketIndex++) { int bucket = buckets[bucketIndex]; if((n > 1)) { sortBucket(bucket); } for(int i=0; i<n; i++) { arr[write] = bucket[i]; recordMetric("outputWrites"); write(write, arr[write]); markSorted(write); write++; } checkpoint(write, n); } }
void recordMetric(int name, int ) { metrics[name] = (((metrics[name]) != 0 ? (metrics[name]) : (0)) + delta); } void sortBucket(int bucket) { recordMetric("bucketSortCalls"); for(int i=1; i<n; i++) { int value = bucket[i]; int j = i; while((j > 0)) { if((bucket[(j - 1)] <= value)) { break; } bucket[j] = bucket[(j - 1)]; j--; recordMetric("bucketShifts"); } bucket[j] = value; } } public void Sort(int[] arr, int n, dynamic stats) { if((n < 2)) { if((n == 1)) { markSorted(0); } return; } int min = arr[0]; int max = arr[0]; for(int i=1; i<n; i++) { if((arr[i] < min)) { min = arr[i]; } if((arr[i] > max)) { max = arr[i]; } } int metrics = stats.educational.metrics; if((min == max)) { for(int i=0; i<n; i++) { markSorted(i); } checkpoint(n, n); return; } int bucketCount = n; int range = (max - min); int[] buckets = new int[bucketCount]; for(int _mi=0;_mi<bucketCount;_mi++) buckets[_mi]=_mi; metrics.bucketCount = bucketCount; for(int i=0; i<n; i++) { int normalized = ((arr[i] - min) / range); int bucketIndex = Math.Min((bucketCount - 1), (int)Math.Floor((double)(normalized * (bucketCount - 1)))); buckets[bucketIndex][buckets[bucketIndex]_len++] = arr[i]; recordMetric("bucketAssignments"); recordMetric("distributionReads"); } int write = 0; for(int bucketIndex=0; bucketIndex<bucketCount; bucketIndex++) { int bucket = buckets[bucketIndex]; if((n > 1)) { sortBucket(bucket); } for(int i=0; i<n; i++) { arr[write] = bucket[i]; recordMetric("outputWrites"); write(write, arr[write]); markSorted(write); write++; } checkpoint(write, n); } }
#include <stdio.h> #include <math.h> #include <stdlib.h> void recordMetric(int name, int ); void sortBucket(int bucket); void recordMetric(int name, int ) { metrics[name] = (((metrics[name]) != 0 ? (metrics[name]) : (0)) + delta); } void sortBucket(int bucket) { recordMetric("bucketSortCalls"); for(int i=1; i<n; i++) { int value = bucket[i]; int j = i; while((j > 0)) { if((bucket[(j - 1)] <= value)) { break; } bucket[j] = bucket[(j - 1)]; j--; recordMetric("bucketShifts"); } bucket[j] = value; } } void sort(int arr[], int n, int* comparisons, int* swaps) { if((n < 2)) { if((n == 1)) { markSorted(0); } return; } int min = arr[0]; int max = arr[0]; for(int i=1; i<n; i++) { if((arr[i] < min)) { min = arr[i]; } if((arr[i] > max)) { max = arr[i]; } } int metrics = (*educational).metrics; if((min == max)) { for(int i=0; i<n; i++) { markSorted(i); } checkpoint(n, n); return; } int bucketCount = n; int range = (max - min); int* buckets = (int*)malloc((bucketCount) * sizeof(int)); for(int _mi=0;_mi<bucketCount;_mi++) buckets[_mi]=_mi; metrics.bucketCount = bucketCount; for(int i=0; i<n; i++) { int normalized = ((arr[i] - min) / range); int bucketIndex = (((bucketCount - 1)) < ((int)floor((normalized * (bucketCount - 1)))) ? ((bucketCount - 1)) : ((int)floor((normalized * (bucketCount - 1))))); buckets[bucketIndex][buckets[bucketIndex]_len++] = arr[i]; recordMetric("bucketAssignments"); recordMetric("distributionReads"); } int write = 0; for(int bucketIndex=0; bucketIndex<bucketCount; bucketIndex++) { int bucket = buckets[bucketIndex]; if((n > 1)) { sortBucket(bucket); } for(int i=0; i<n; i++) { arr[write] = bucket[i]; recordMetric("outputWrites"); write(write, arr[write]); markSorted(write); write++; } checkpoint(write, n); } }