一、性能描述
桶排序
维度 | 描述 |
---|---|
时间复杂度 | - 平均:O(n + k)(k为桶数量) - 最坏:O(n²)(所有元素集中在1个桶) |
空间复杂度 | O(n + k)(需要额外存储桶结构) |
关键影响因素 | - 桶的数量与数据分布的匹配度 - 桶内排序算法的选择(如插入排序 vs 归并排序) |
基数排序
维度 | 描述 |
---|---|
时间复杂度 | O(d*(n + k))(d为最大位数,k为基数,如10进制中k=10) |
空间复杂度 | O(n + k)(计数排序的额外空间) |
关键影响因素 | - 最大位数d的大小 - 基数选择(10进制、256进制等) |
二、核心差异对比
维度 | 桶排序 | 基数排序 |
---|---|---|
排序方式 | 按数据范围分桶,桶内独立排序 | 按位数逐位排序(从低位到高位) |
稳定性 | 稳定(取决于桶内排序算法是否稳定) | 稳定(依赖底层计数排序的稳定性) |
数据类型 | 适合浮点数、整数(需均匀分布) | 仅适用于整数或可离散化的数据(如字符串) |
空间占用 | 桶数量多时空间开销较大 | 空间固定(由基数和数据量决定) |
预处理成本 | 需要合理设计桶的划分策略 | 需要计算最大位数 |
三、适用场景
桶排序
-
均匀分布数据
数据分布均匀时,分桶后各桶元素数量均衡,效率接近线性。
示例场景:- 对年龄在0~100岁的人群按年龄段分组排序
- 对0~1之间的浮点数排序(如科学计算中的采样数据)
-
外部排序(数据量极大)
桶排序可将数据分到不同文件(桶),逐批加载到内存排序,适合处理超出内存的数据。
示例场景:- 大型日志文件按时间范围分块排序
-
非比较型排序需求
当数据比较成本高时,桶排序通过分桶避免直接比较。
基数排序
-
固定位数整数排序
当整数位数固定或范围可控时,基数排序效率极高。
示例场景:- 手机号排序(11位固定长度)
- 身份证号排序(18位固定长度)
-
多关键字排序
可逐位(或逐字段)排序,适合多维度排序需求。
示例场景:- 先按月份、再按日期对日期列表排序
- 按优先级+时间戳对任务排序
-
稳定排序需求
需要保持相同元素的原始顺序时,基数排序天然稳定。
四、实际代码差异示例
桶排序处理浮点数
public static void bucketSortForFloats(float[] arr) {
int n = arr.length;
List<Float>[] buckets = new ArrayList[n];
for (int i = 0; i < n; i++) {
buckets[i] = new ArrayList<>();
}
// 分桶(假设数据在0~1之间)
for (float num : arr) {
int bucketIdx = (int) (num * n);
buckets[bucketIdx].add(num);
}
// 对每个桶排序并合并
int idx = 0;
for (List<Float> bucket : buckets) {
Collections.sort(bucket);
for (float num : bucket) {
arr[idx++] = num;
}
}
}
基数排序处理字符串
public static void radixSortForStrings(String[] arr) {
int maxLength = Arrays.stream(arr).mapToInt(String::length).max().orElse(0);
for (int i = maxLength - 1; i >= 0; i--) {
countingSortByCharacter(arr, i);
}
}
private static void countingSortByCharacter(String[] arr, int charIdx) {
int n = arr.length;
String[] output = new String[n];
int[] count = new int[256]; // ASCII范围
for (String s : arr) {
int c = (charIdx < s.length()) ? s.charAt(charIdx) : 0;
count[c]++;
}
for (int i = 1; i < 256; i++) {
count[i] += count[i - 1];
}
for (int i = n - 1; i >= 0; i--) {
String s = arr[i];
int c = (charIdx < s.length()) ? s.charAt(charIdx) : 0;
output[count[c] - 1] = s;
count[c]--;
}
System.arraycopy(output, 0, arr, 0, n);
}
五、总结
算法 | 优势 | 劣势 | 长青场景 |
---|---|---|---|
桶排序 | 灵活处理浮点数、适合外部排序 | 依赖数据分布,桶划分策略敏感 | 均匀分布数据、大数据分块处理 |
基数排序 | 高效处理固定位数整数、天然稳定 | 仅限离散化数据、预处理成本较高 | 手机号/身份证号排序、多关键字排序需求 |
选择建议:
- 若数据为整数且位数较少 → 基数排序
- 若数据为浮点数且分布均匀 → 桶排序
- 若需要稳定排序且数据可离散化 → 基数排序
- 若数据量极大需分治处理 → 桶排序