Please enable Javascript to view the contents

菜鸟学算法-8-桶排序

 ·  ☕ 2 分钟

我想知道这是为什么 –费曼

桶排序:
先分类,把数据放进相应的桶里,然后对每个桶进行局部排序,最后再把桶排序一下

有四步:

1.创建桶

2.归类(把元素放到对应的桶里)

3.排序

4.合并

创建桶

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
let array = [3, 8, 6, 1, 5, 7, 9, 2, 4]
let min = Math.min(...array)
let max = Math.max(...array)
let size = 3
let count = Math.floor((max - min) / size) + 1 // count从1开始计算需要加1
let buckets = []
for (let i = 0; i < count; i++) {
  buckets.push([])
}
console.log(buckets) // [ [], [], []]

归类

1
2
3
4
5
6
for (let value of array) {
  let bucketIndex = Math.floor((vlaue - min) / size) // bucketIndex从0开始计算不需要加1
  buckets[bucketIndex].push(value)
}

console.log(buckets) // [ [ 3, 1, 2 ], [ 6, 5, 4 ], [ 8, 7, 9 ] ]

排序 && 合并

排序用其他任一排序算法都可以,比如数据量不太大的时候,插入排序就比较适合

因为区间本来就是有序的,合并的时候直接链接这些数组就可以了

1
2
3
4
5
6
let result = []
for (let bucket of buckets) {
  result.push(...insertionSort(bucket))
}

console.log(result) // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

完整代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 桶排序
function bucketSort(array, size = 10) {
  let max = Math.max(...array)
  let min = Math.min(...array)
  let count = Math.floor((max - min) / size) + 1
  let buckets = []
  for (let i = 0; i < count; i++) {
    buckets.push([])
  }

  for (let value of array) {
    let bucketIndex = Math.floor((value - min) / size)
    buckets[bucketIndex].push(value)
  }

  let result = []
  for (let bucket of buckets) {
    result.push(...insertionSort(bucket))
  }
  return result
}

// 插入排序
function insertionSort(array) {
  for (let i = 1; i < length; i++) {
    let j = i
    let target = array[j]
    while (j > 0 && array[j - 1] > target) {
      array[j] = array[j - 1]
      j--
    }
    array[j] = target
  }
  return array
}

复杂度 && 总结

桶排序是分布式排序,适合处理大批量数据。需要额外空间,是外部排序。
桶排序是否稳定,取决于第二步排序算法的选择。
时间复杂度是线性级 O(n),可以简单理解:桶的范围大小是人为指定的,它不随数据规模变化,如果数据相对均匀分布,那么桶的个数就是核心影响因子了。


我创建了一个集合 jest 可以测试算法的靶场项目:
https://github.com/Llane00/algorithm-range-tests
将同步文章中的代码到这个项目下

使用 vscode 的读者可以安装拓展插件 jest,这个插件可以自动检测 test 文件自动运行,非常方便。


分享

Llane00
作者
Llane00
Web Developer