algorighm/sort/radix-sort.mjs
2024-05-02 00:24:25 +08:00

82 lines
2.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import insertionSort from './insertion-sort.mjs';
/**
* 使用lsd基数排序
* @param {number[]} arr - 要基数排序的数组
*/
export function radixSortByLsd(arr) {
let max = Math.abs(Math.max(...arr)); // 拿取数组中最大的数,用于计算长度
let buckets = Array.from({ length: 10 }, () => []);
let curDit = 1; // 当前比较的是哪个数位 1表示个位
/* 处理负数,思路: 把所有的负数和正数都分开,负数使用绝对值处理之后以同样的方法处理,处理完之后取相反数再
倒序添加到原数组的前面
*/
let negativeArr = [];
const tempArr = [];
for (let i = 0; i < arr.length; i++) {
const temp = arr[i];
if (temp < 0) {
negativeArr.push(temp);
} else {
tempArr.push(temp);
}
}
arr = tempArr;
if (negativeArr.length) {
negativeArr = radixSortByLsd(negativeArr.map((_) => -_)).map((_) => -_);
}
while (Math.floor(max)) {
for (let i = 0; i < arr.length; i++) {
buckets[getNumByGidit(arr[i], curDit)].push(arr[i]); // 根据数位的大小放入对应的数位桶中
}
// 对buckets中的每个桶的元素做好排序这里我们调用之前的插入排序
for (let i = 0; i < buckets.length; i++) {
insertionSort(buckets[i]);
}
// 个位比较完成之后比较十位,在此之前要把个位有序的数组给原数组,并且把桶子清空
arr = buckets.flat();
buckets = Array.from({ length: 10 }, () => []);
max /= 10; // 处理下一数位
curDit++;
}
return negativeArr.length ? negativeArr.reverse().concat(arr) : arr;
}
/**
* @description 获取某位的数字,从1开始1代表是个位比如1003返回的是13代表千位
* @param {number} num - 传入的数值
* @param {number} dit - 要获取的位数
*/
function getNumByGidit(num, dit) {
if (!num) return 0;
let res = 0;
while (dit--) {
res = num % 10;
num = (num - res) / 10;
}
return res;
}
/**
* @description 使用msd的基数排序
* @param {number[]} arr - 需要排序的数组
*/
export function radixSortByMsd(arr) {
// 获取最大值,并通过最大值对小的数补零
const maxVal = Math.max(...arr);
const n = arr.length; // 数组的个数
const radix = Math.floor(Math.log10(maxVal)); // 对应的位数比如100就是2代表百分位
// 从高位到地位开始比较,分别放入对应的桶中,再便利,使之相对有序
const buckets = Array.from({ length: 10 }, () => []);
for (let i = 0; i < n; i++) {
buckets[getNumByGidit(arr[i], radix + 1)].push(arr[i]);
}
// 对每一个桶中的内容进行msd基数排序如果零号桶还有的话
if (buckets[0].length) {
for (let i = 0; i < buckets.length; i++) {
buckets[i] = radixSortByMsd(buckets[i]);
}
}
return buckets.flat();
}