Skip to content

桶排序 (Bucket Sort)

高效与否的关键在于这个分桶函数。将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。

算法描述

  • 设置一个定量的数组当作空桶;
  • 遍历输入数据,并且把数据一个一个放到对应的桶里去;
  • 对每个不是空的桶进行排序;
  • 从不是空的桶里把排好序的数据拼接起来。

代码演示

ts
const count = (list: Array<number>, max: number = 100): Array<number> => {
  const countList = new Array(max + 1);
  for (let i = 0; i < list.length; i++) {
    if (!countList[list[i]]) {
      countList[list[i]] = 0;
    }
    countList[list[i]]++;
  }
  let startIndex = 0;
  for (let i = 0; i < countList.length; i++) {
    while (countList[i] > 0) {
      list[startIndex++] = i;
      countList[i]--;
    }
  }
  return list;
};
const getMax = (list: Array<number>) => {
  let max = list[0];
  for (let i = 0; i < list.length; i++) {
    if (max < list[i]) {
      max = list[i];
    }
  }
  return max;
};
const getMin = (list: Array<number>) => {
  let min = list[0];
  for (let i = 0; i < list.length; i++) {
    if (min > list[i]) {
      min = list[i];
    }
  }
  return min;
};

/**
 * @description: 桶排序
 * @param {Array<number>} list
 * @return {Array<number>}
 */
const bucket = (list: Array<number>, bucketSize: number = 5, max?: number, min?: number): Array<number> => {
  if (list.length === 0) return list;
  if (!max) max = getMax(list);
  if (!min) min = getMin(list);
  const bucketCount = Math.floor((max - min) / bucketSize) + 1;
  const buckets = new Array(bucketCount + 1).fill(0).map(() => new Array(0));

  for (let i = 0; i < list.length; i++) {
    buckets[Math.floor((list[i] - min) / bucketSize)].push(list[i]);
  }
  list = [];
  for (let i = 0; i < bucketCount; i++) {
    list = list.concat(count(buckets[i]));
  }
  return list;
};

算法分析

桶排序最好情况下使用线性时间 O(n),桶排序的时间复杂度,取决与对各个桶之间数据进行排序的时间复杂度,因为其它部分的时间复杂度都为 O(n)。很显然,桶划分的越小,各个桶之间的数据越少,排序所用的时间也会越少。但相应的空间消耗就会增大。

Released under the MIT License.