桶排序
基本思想
桶排序采用分治策略,通过设置若干个具有大小顺序的桶,每个桶对应一个数据范围,将数据平均分配到各个桶中,然后,在每个桶内部执行排序,最终按照桶的顺序将所有数据合并。
实现思路
- 初始化k个桶,将n个元素分配到k个桶中
- 对每个桶分别执行排序
- 按照桶的从小到大的顺序,合并数组
代码实现
function bucketSort(array, bucketSize = 5) { // bucktsize为每个桶中元素默认的数量
if (array.length < 2) {
return array
}
const buckets = createBuckets(array, bucketSize) // 创建桶
return sortBuckets(buckets) // 桶的排序合并
}
function createBuckets(array, bucketSize) {
// 假设第一个值为最大值和最小值
let minValue = array[0]
let maxValue = array[0]
for (let i = 1; i < array.length; i++) { // 遍历数组找到真实的最大值和最小值
if (array[i] < minValue) {
minValue = array[i]
} else if (array[i] > maxValue) {
maxValue = array[i]
}
}
const bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1 // 计算桶的数量公式
const buckets = [] // 初始化桶
for (let i = 0; i < bucketCount; i++) { // 插入bucketCount数量个桶
buckets[i] = []
}
for (let i = 0; i < array.length; i++) { // 遍历数组计算插入到哪个桶
const bucketIndex = Math.floor((array[i] - minValue) / bucketSize) // 计算该插入哪个桶
buckets[bucketIndex].push(array[i]) // 将数据插入对应的桶
}
return buckets
}
function sortBuckets(buckets) {
const sortedArray = [] // 结果数组
for (let i = 0; i < buckets.length; i++) {
if (buckets[i] != null) {
insertionSort(buckets[i]) // 使用插入排序排序每个桶---在算法排序篇-3中实现的插入排序函数
sortedArray.push(...buckets[i]) // 将各个桶添加到结果数组中
}
}
return sortedArray
}
function insertionSort(array) {
const { length } = array
let temp // 存储要插入的值
for (let i = 1; i < length; i++) { // 默认数组有一项,从1开始
let j = i
temp = array[i] // 存储要插入的值
while(j > 0 && (array[j - 1] > temp)) { // 如果要插入的值的前一项比要插入的值大,则插入的前一项向后面移一位,而插入的值再与前面的值相比较,直到找到合适的位置(j),同时j索引减少到合适的位置
array[j] = array[j - 1]
j--
}
array[j] = temp // 找到合适的位置,插入要插入的值
}
return array
}
const array = [23,2,24,5,7,232,8,3,9,11]
console.log(bucketSort(array)); // [ 2, 3, 5, 7, 8, 9, 11, 23, 24, 232]