请问:基于MSD Sort的BucketSort,虽然支持整型数字排序,是不是浮点数排序就不适用,就只能采用比较排序算法了?
由于BucketSort 是基于MSDSort,根据最大值和最小值算出一个区间,然后根据桶大小,将区间数据平分值各个桶中,如果是浮点数的话,由于浮点数变化范围太大,而且区间也不好计算。比如:0.12333,0.12334,1.333,2.45…等等。是不是浮点数就不太适合用桶排序,只能采用比较算法排序了?
正在回答 回答被采纳积分+1
首先,我们通常将 MSD Sort 和 LSD Sort 归类到基数排序(Radix Sort)中,虽然或许我在课程中说过 MSD Sort 和 LSD Sort 也使用了“桶”的思想。
桶排序的思路完全可以应用于浮点数中,整体思路一样:根据浮点数的最大值,最小值,计算出数据分布的区间,将整个区间分为 B 个桶,然后依次把数据放到不同的桶中,递归下去。
从计算的角度,整个过程和整数的桶排序区别不大。区间大小就是最大值和最小值的差;每个桶涵盖的区间大小就是 珍格格区间大小 / B,每个区间的起始位置就是 (最小值 + 区间大小 * 桶编号) 等等等等。所以算法的逻辑流程是一致的。对于浮点数来说,一切问题的核心是:引入过多的计算,就会积累浮点误差。从这个意义上讲:是的,浮点数用比较排序是最好的。
==========
事实上,近乎任何数据,没有特殊情况,使用比较排序都是不差的。这就是为什么,对于一般的语言标准库,提供的排序接口,背后都是比较排序(通常稳定排序用归并或基于归并改进的排序;不要求稳定的排序使用快排或基于快排改进的排序。);
这也是为什么非比较排序虽然理论复杂度是 O(n),但并不经常使用(实际性能可能不如 O(nlogn));
这也是为什么在大多数情况,非比较排序根本不会在面试中出现。
==========
但是,非比较排序的这个思路,是非常有意义的。关键就是"桶"的思想本身,其实是一个很常用的算法或者数据结构思路。从哈希表,到分块儿类的问题处理(比如 sqrt 分解),本质都是在用“桶”的思想。
继续加油!:)
通过这两天思考,找到一个解决办法,就是将浮点数转成整数不就可以复用之前的逻辑了嚒。按照这个思路解决了,在此分享给大家。
/** * 简版Bucket Sort * 支持:整数和浮点数 * @param {*} nums */ function bucketSort(nums) { let minV = Number.MAX_SAFE_INTEGER; let maxV = Number.MIN_SAFE_INTEGER; //! 1.计算区间 和 用set计算所需的桶数量 let set = new Set(); let maxFLen = Number.MIN_SAFE_INTEGER; for (let i = 0; i < nums.length; i++) { minV = Math.min(minV, nums[i]); maxV = Math.max(maxV, nums[i]); set.add(nums[i]); //! 说明:截取最长的小数位长度 let sF = nums[i].toString(); sF = sF.indexOf(".") >= 0 ? sF.slice(sF.indexOf(".") + 1) : sF; nFlen = sF.length; if (nFlen > maxFLen) { maxFLen = nFlen; } } //! 根据最长的小数位长度,然后乘以maxFlen个10,此时所以浮点数就都可以转成整数,然后就可以复用桶排序思想进行排序 let base = 10 ** maxFLen; //! 说明:相乘会有精度问题,向上取整保证数值范围在此区间中 minV = Math.ceil(minV * base); maxV = Math.ceil(maxV * base); //! 2.计算取值范围R let R = maxV - minV + 1; let B = set.size; let c = Math.floor(R / B) + (R % B > 0 ? 1 : 0); //! 3.初始化桶 let buckets = Array(B); for (let i = 0; i < buckets.length; i++) { buckets[i] = []; } //! 4.遍历每个元素,让将其放入对应桶中 for (const num of nums) { buckets[Math.floor((num * base - minV) / c)].push(num); } //! 5.对每个桶进行排序 for (let i = 0; i < buckets.length; i++) { buckets[i].sort((a, b) => a - b); } //! 6.遍历每个的元素,然后重新赋值给nums数组 let index = 0; for (let bucket of buckets) { for (let e of bucket) { nums[index] = e; index++; } } } let arr = [0.1, 2.33, -3.1111, 2, -5.05, 10.04, 4.1]; bucketSort(arr, 3); arr.forEach((v) => console.log(v));
输出结果:
-5.05 -3.1111 0.1 2 2.33 4.1 10.04
不知道大家还有没有更好的解决思路
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星