「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战」
算法思想
桶排序是划分多个范围相同的区间(桶),将待排序区间内的元素映射到对应的区间(桶)中,每个区间中的元素再进行排序,然后合并到一个新的区间。桶排序其实就是计数排序的扩展版本(想了解什么是计数排序请观看 这篇文章),计数排序可以看成是每个桶只存放一个元素,桶排序的每个桶需要存放一定范围的元素,最后都需要开辟一个新空间用于存放结果。
图解算法
- 确定桶的个数以及每个桶的范围,
- 将原数组中的元素依次放入对应的桶中
- 每个桶再单独排序,这里的排序可以用到插入排序
4. 将桶数组中的元素依次输出到新的存储空间
代码实现
- 先来看一下计数排序的实现
function countSort(arr) {
let max = -Infinity,
min = Infinity
for (let v of arr) {
max = Math.max(max, v)
min = Math.min(min, v)
}
const count = new Array(max - min + 1).fill(0) //数组长度最大值-最小值,最小值变成下标0,
// 如果最大值和最小值差距很大,仍然存在空间浪费的情况
for (let v of arr) {
count[v - min]++ //需要减去最小值
}
const res = []
for (let i = 0; i < count.length; i++) {
let tmp = count[i]
while (tmp--) {
res.push(i + min) //这里要加回来
}
}
return res
}
const arr = [-101, 109, 107, 103, 108, 102, 103, 110, 107, 103]
console.log(countSort(arr)) //[-101, 102, 103, 103, 103, 107, 107, 108, 109, 110]
- 桶排序在计数排序的基础上划分了桶,减少了空间的浪费
function bucketSort(arr) {
// 找到最大值与最小值
let max = -Infinity,
min = Infinity
for (let v of arr) {
max = Math.max(max, v)
min = Math.min(min, v)
}
// 生成桶数组
const bucketNum = Math.floor((max - min) / arr.length) + 1 //桶数量
let bucketArr = new Array(bucketNum).fill(null)
bucketArr = bucketArr.map(_ => [])
// 每个元素放入桶
for (let v of arr) {
let index = Math.floor((v - min) / arr.length)
bucketArr[index].push(v)
}
// 结果数组
const res = []
for (let item of bucketArr) {
// 可进行其他排序
item.sort((a, b) => a - b)
// 输出
for (let v of item) {
res.push(v)
}
}
return res
}
const arr = [14, 28, 10, 24, 35, 50, 39, 47]
console.log(bucketSort(arr)) // [10, 14, 24, 28, 35, 39, 47, 50]
-- end --