SortVision项目中的基数排序JavaScript实现解析
基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。本文将深入解析如何在SortVision项目中实现一个高效且功能完备的基数排序算法。
算法核心思想
基数排序的基本思想是"分配"和"收集"。它不需要比较关键字的大小,而是根据关键字的每个位上的数字来分配和收集元素。具体来说:
- 首先找出待排序数组中最大数的位数
- 从最低位开始,对每一位进行稳定的排序(通常使用计数排序)
- 重复这个过程直到最高位排序完成
这种算法的优势在于其时间复杂度可以达到O(nk),其中n是元素数量,k是数字位数,这使得它在某些场景下比O(nlogn)的比较排序算法更高效。
JavaScript实现要点
获取最大数值
实现基数排序的第一步是确定需要处理的位数,这通过找出数组中的最大值来实现:
function getMax(arr) {
let max = arr[0];
for (let i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
计数排序辅助函数
基数排序依赖于稳定的排序算法来处理每一位,通常使用计数排序:
function countSort(arr, exp, base = 10) {
const output = new Array(arr.length).fill(0);
const count = new Array(base).fill(0);
// 统计当前位数字出现的次数
for (let i = 0; i < arr.length; i++) {
const digit = Math.floor(arr[i] / exp) % base;
count[digit]++;
}
// 计算累计位置
for (let i = 1; i < base; i++) {
count[i] += count[i - 1];
}
// 构建输出数组
for (let i = arr.length - 1; i >= 0; i--) {
const digit = Math.floor(arr[i] / exp) % base;
output[count[digit] - 1] = arr[i];
count[digit]--;
}
// 复制回原数组
for (let i = 0; i < arr.length; i++) {
arr[i] = output[i];
}
}
完整的基数排序实现
结合上述辅助函数,我们可以实现完整的基数排序:
function radixSort(arr, base = 10) {
if (arr.length <= 1) return arr;
// 处理负数:分离正负数,分别排序后合并
const negatives = arr.filter(x => x < 0).map(x => -x);
const positives = arr.filter(x => x >= 0);
// 对正数部分排序
if (positives.length > 0) {
const max = getMax(positives);
for (let exp = 1; Math.floor(max / exp) > 0; exp *= base) {
countSort(positives, exp, base);
}
}
// 对负数部分排序(取绝对值后排序,再反转并恢复负号)
if (negatives.length > 0) {
const max = getMax(negatives);
for (let exp = 1; Math.floor(max / exp) > 0; exp *= base) {
countSort(negatives, exp, base);
}
negatives.reverse();
for (let i = 0; i < negatives.length; i++) {
negatives[i] = -negatives[i];
}
}
return [...negatives, ...positives];
}
关键特性实现
多进制支持
通过添加base参数,算法可以支持不同的进制系统。例如,base=2可用于二进制排序,base=16可用于十六进制排序。这在处理特殊数据格式时非常有用。
负数处理
基数排序通常只处理非负整数。我们的实现通过以下步骤处理负数:
- 分离正数和负数
- 对负数取绝对值后排序
- 排序后反转顺序并恢复负号
- 最后合并正数和负数部分
性能优化
- 提前终止:当exp超过最大值时停止处理
- 内存复用:尽量复用数组减少内存分配
- 类型稳定:保持原始数组类型不变
复杂度分析
- 时间复杂度:O(nk),其中n是元素数量,k是数字位数
- 空间复杂度:O(n + b),其中b是基数(进制数)
- 稳定性:基数排序是稳定的排序算法
实际应用示例
// 十进制排序
console.log(radixSort([170, 45, 75, 90, 802, 24, 2, 66]));
// 输出: [2, 24, 45, 66, 75, 90, 170, 802]
// 二进制排序
console.log(radixSort([5, 3, 7, 1], 2));
// 输出: [1, 3, 5, 7]
// 包含负数的排序
console.log(radixSort([-5, 3, -7, 1]));
// 输出: [-7, -5, 1, 3]
适用场景与限制
基数排序特别适合:
- 整数或固定格式字符串的排序
- 数据范围不是特别大的情况
- 需要稳定排序的场景
但它也有局限性:
- 不适用于浮点数排序
- 当数据范围很大时,效率可能降低
- 需要额外的内存空间
通过这样的实现,SortVision项目获得了一个功能完备、高效且灵活的基数排序算法,能够处理各种数值排序需求。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考