如何修改基于十进制的LSD基数排序程序的基数?
修改LSD基数排序以支持任意基数
核心问题分析
你的原代码存在两个关键硬编码问题,导致无法适配其他基数:
- 固定使用十进制的数字组(
[0,1,...,9])和循环次数(10次) - 通过字符串索引取位的方式仅适用于十进制,无法处理任意基数的位计算
关键修改点
- 将基数作为参数传入:让函数支持自定义基数,默认保留十进制
- 用数学方法计算当前位数值:替代字符串操作,通用公式为
Math.floor((num / Math.pow(base, digit)) % base),其中digit是当前处理的位数(从0开始,0代表最低位) - 替换硬编码的十进制常量:所有和10相关的数值(比如桶的数量、循环次数)都替换为传入的基数参数
- 使用数组桶替代对象映射:更高效且符合基数排序的标准实现方式
修改后的完整代码
async function radix(array, base = 10) { // 创建对应基数的桶数组,每个桶是一个空数组 const buckets = Array.from({ length: base }, () => []); let res = [...array]; let loop = -1; // 找到数组中的最大值,确定需要处理的最大位数 const maxNum = Math.max(...res); const maxDigits = maxNum === 0 ? 1 : Math.floor(Math.log(maxNum) / Math.log(base)) + 1; for (let digit = 0; digit < maxDigits; digit++) { // 清空所有桶 buckets.forEach(bucket => bucket.length = 0); for (let idx = 0; idx < res.length; idx++) { loop++; checks++; draw(res, sound=false); osc.stop(); osc = playSound(res[idx] * 2); ctx.fillStyle = 'blue'; ctx.fillRect(idx * canvas.width / res.length, canvas.height - res[idx], canvas.width / res.length, res[idx]); await sleep(wait_time); // 计算当前位的数值 const num = res[idx]; const currentDigit = Math.floor((num / Math.pow(base, digit)) % base); // 将数字放入对应桶中 buckets[currentDigit].push(num); } // 从桶中依次取出,合并为新的有序数组 res = buckets.flat(); // 绘制当前排序状态 draw(res); await sleep(0.00001); } return res; }
代码说明
- 基数参数:新增
base参数,默认值为10,调用时可传入任意大于1的整数(比如radix(arr, 2)实现二进制基数排序) - 位数计算:通过
Math.log(maxNum)/Math.log(base)计算最大值在目标基数下的位数,确保处理所有有效位 - 桶操作:每次处理一位时,将数字按当前位数值放入对应桶,再按桶的顺序合并,保证低位有序
- 保留原有交互:保留了原代码中的绘图、声音和等待逻辑,不影响可视化效果
内容的提问来源于stack exchange,提问作者piro2
相关产品推荐
相关产品推荐

