From be99d65f0508680a1fa9df0f93873e3dce6a692a Mon Sep 17 00:00:00 2001 From: = <--gbloal> Date: Thu, 2 May 2024 00:24:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=9F=BA=E6=95=B0?= =?UTF-8?q?=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sort/radix-sort.mjs | 81 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 sort/radix-sort.mjs diff --git a/sort/radix-sort.mjs b/sort/radix-sort.mjs new file mode 100644 index 0000000..5df21bd --- /dev/null +++ b/sort/radix-sort.mjs @@ -0,0 +1,81 @@ +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代表是个位,比如(100,3)返回的是1,3代表千位 + * @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(); +}