桶排序
实现桶排序算法及其原理
问题
实现桶排序算法,理解其工作原理和适用场景。
解答
桶排序是一种分布式排序算法,将元素分散到多个桶中,每个桶单独排序后再合并。
基本实现
function bucketSort(arr, bucketSize = 5) {
if (arr.length === 0) return arr;
// 找出最大值和最小值
let min = arr[0];
let max = arr[0];
for (let i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
} else if (arr[i] > max) {
max = arr[i];
}
}
// 计算桶的数量
const bucketCount = Math.floor((max - min) / bucketSize) + 1;
// 创建桶
const buckets = new Array(bucketCount);
for (let i = 0; i < bucketCount; i++) {
buckets[i] = [];
}
// 将元素分配到桶中
for (let i = 0; i < arr.length; i++) {
const bucketIndex = Math.floor((arr[i] - min) / bucketSize);
buckets[bucketIndex].push(arr[i]);
}
// 对每个桶内部排序,然后合并
const result = [];
for (let i = 0; i < buckets.length; i++) {
// 桶内使用插入排序(小数据量时效率高)
insertionSort(buckets[i]);
result.push(...buckets[i]);
}
return result;
}
// 插入排序(用于桶内排序)
function insertionSort(arr) {
for (let i = 1; i < arr.length; i++) {
const current = arr[i];
let j = i - 1;
while (j >= 0 && arr[j] > current) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = current;
}
return arr;
}
// 测试
const arr = [0.42, 0.32, 0.23, 0.52, 0.25, 0.47, 0.51];
console.log(bucketSort(arr, 0.1));
// [0.23, 0.25, 0.32, 0.42, 0.47, 0.51, 0.52]
针对 0-1 范围浮点数的优化版本
function bucketSortFloat(arr, bucketCount = 10) {
if (arr.length === 0) return arr;
// 创建桶
const buckets = Array.from({ length: bucketCount }, () => []);
// 分配元素到桶(假设元素在 [0, 1) 范围内)
for (const num of arr) {
const index = Math.floor(num * bucketCount);
// 处理边界情况:num === 1 时放入最后一个桶
const bucketIndex = index === bucketCount ? bucketCount - 1 : index;
buckets[bucketIndex].push(num);
}
// 桶内排序并合并
return buckets.flatMap(bucket => bucket.sort((a, b) => a - b));
}
// 测试
const floats = [0.78, 0.17, 0.39, 0.26, 0.72, 0.94, 0.21, 0.12, 0.23, 0.68];
console.log(bucketSortFloat(floats));
// [0.12, 0.17, 0.21, 0.23, 0.26, 0.39, 0.68, 0.72, 0.78, 0.94]
图解过程
原始数组: [0.42, 0.32, 0.23, 0.52, 0.25, 0.47, 0.51]
分桶(桶大小 0.1):
桶[2]: [0.23, 0.25]
桶[3]: [0.32]
桶[4]: [0.42, 0.47]
桶[5]: [0.52, 0.51]
桶内排序:
桶[2]: [0.23, 0.25]
桶[3]: [0.32]
桶[4]: [0.42, 0.47]
桶[5]: [0.51, 0.52]
合并: [0.23, 0.25, 0.32, 0.42, 0.47, 0.51, 0.52]
关键点
- 时间复杂度:平均 O(n + k),最坏 O(n²),k 为桶的数量
- 空间复杂度:O(n + k),需要额外空间存储桶
- 适用场景:数据分布均匀、范围已知的情况,如 0-1 之间的浮点数
- 桶大小选择:桶太少导致桶内元素多,桶太多浪费空间,通常取 n 或 √n
- 非比较排序:通过分布而非比较来排序,可突破 O(n log n) 的下界
目录