桶排序算法

桶排序(Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶里。每个桶再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间

Theta (n)
。但桶排序并不是比较排序,他不受到
O(n\log n)
下限的影响。

桶排序以下列步骤进行:

  1. 设置一个定量的数组当作空桶子。
  2. 寻访序列,并且把项目一个一个放到对应的桶子去。
  3. 对每个不是空的桶子进行排序。
  4. 从不是空的桶子里把项目再放回原来的序列中。

桶排序图示

  • 数据结构: 数组
  • 最坏时间复杂度
    O(n^{2})
  • 平均时间复杂度
    O(n+k)
  • 最坏空间复杂度
    (n\cdot k)}

元素分配到桶中

对桶中元素排序

伪代码

function bucket-sort(array, n) is
  buckets  new array of n empty lists
  for i = 0 to (length(array)-1) do
    insert array[i] into buckets[msbits(array[i], k)]
  for i = 0 to n - 1 do
    next-sort(buckets[i])
  return the concatenation of buckets[0], ..., buckets[n-1]

实现示例

C++ 实现桶排序

假设数据分布在[0,100)之间,每个桶内部用链表表示,在数据入桶的同时插入排序。然后把各个桶中的数据合并。

#include<iterator>
#include<iostream>
#include<vector>
using namespace std;
const int BUCKET_NUM = 10;

struct ListNode{
  explicit ListNode(int i=0):mData(i),mNext(NULL){}
  ListNode* mNext;
  int mData;
};

ListNode* insert(ListNode* head,int val){
  ListNode dummyNode;
  ListNode *newNode = new ListNode(val);
  ListNode *pre,*curr;
  dummyNode.mNext = head;
  pre = &dummyNode;
  curr = head;
  while(NULL!=curr && curr->mData<=val){
    pre = curr;
    curr = curr->mNext;
  }
  newNode->mNext = curr;
  pre->mNext = newNode;
  return dummyNode.mNext;
}


ListNode* Merge(ListNode *head1,ListNode *head2){
  ListNode dummyNode;
  ListNode *dummy = &dummyNode;
  while(NULL!=head1 && NULL!=head2){
    if(head1->mData <= head2->mData){
      dummy->mNext = head1;
      head1 = head1->mNext;
    }else{
      dummy->mNext = head2;
      head2 = head2->mNext;
    }
    dummy = dummy->mNext;
  }
  if(NULL!=head1) dummy->mNext = head1;
  if(NULL!=head2) dummy->mNext = head2;
  
  return dummyNode.mNext;
}

void BucketSort(int n,int arr[]){
  vector<ListNode*> buckets(BUCKET_NUM,(ListNode*)(0));
  for(int i=0;i<n;++i){
    int index = arr[i]/BUCKET_NUM;
    ListNode *head = buckets.at(index);
    buckets.at(index) = insert(head,arr[i]);
  }
  ListNode *head = buckets.at(0);
  for(int i=1;i<BUCKET_NUM;++i){
    head = Merge(head,buckets.at(i));
  }
  for(int i=0;i<n;++i){
    arr[i] = head->mData;
    head = head->mNext;
  }
}

java 实现桶排序

private int indexFor(int a, int min, int step) {
  return (a - min) / step;
}

public void bucketSort(int[] arr) {
  int max = arr[0], min = arr[0];
  for (int a : arr) {
    if (max < a)
      max = a;
    if (min > a)
      min = a;
  }
  // 該值也可根據實際情況選擇
  int bucketNum = max / 10 - min / 10 + 1;
  List buckList = new ArrayList<List<Integer>>();
  // create bucket
  for (int i = 1; i <= bucketNum; i++) {
    buckList.add(new ArrayList<Integer>());
  }
  // push into the bucket
  for (int i = 0; i < arr.length; i++) {
    int index = indexFor(arr[i], min, 10);
    ((ArrayList<Integer>) buckList.get(index)).add(arr[i]);
  }
  ArrayList<Integer> bucket = null;
  int index = 0;
  for (int i = 0; i < bucketNum; i++) {
    bucket = (ArrayList<Integer>) buckList.get(i);
    insertSort(bucket);
    for (int k : bucket) {
      arr[index++] = k;
    }
  }
}

// 把桶內元素插入排序
private void insertSort(List<Integer> bucket) {
  for (int i = 1; i < bucket.size(); i++) {
    int temp = bucket.get(i);
    int j = i - 1;
    for (; j >= 0 && bucket.get(j) > temp; j--) {
      bucket.set(j + 1, bucket.get(j));
    }
    bucket.set(j + 1, temp);
  }
}

JavaScript 实现桶排序

Array.prototype.bucketSort = function(num) {
  function swap(arr, i, j) {
    const temp = arr[i]
    arr[i] = arr[j]
    arr[j] = temp
  }
  const max = Math.max(...this)
  const min = Math.min(...this)
  const buckets = []
  const bucketsSize = Math.floor((max - min) / num) + 1
  for(let i = 0; i < this.length; i++) {
    const index = ~~(this[i] / bucketsSize)
    !buckets[index] && (buckets[index] = [])
    buckets[index].push(this[i])
    let l = buckets[index].length
    while(l > 0) {
      buckets[index][l] < buckets[index][l - 1] && swap(buckets[index], l, l - 1)
      l--
    }
  }
  let wrapBuckets = []
  for(let i = 0; i < buckets.length; i++) {
    buckets[i] && (wrapBuckets = wrapBuckets.concat(buckets[i]))
  }
  return wrapBuckets
}
const arr = [11, 9, 6, 8, 1, 3, 5, 1, 1, 0, 100]
console.log(arr.bucketSort(10))
JavaScript实现递归算法
Array.prototype.bucketSort = function()
{
  var start = 0;
  var size = this.length;
  var min = this[0];
  var max = this[0]; 
  for (var i = 1; i < size; i++){
    if (this[i] < min){min = this[i];}
    else{ if(this[i] > max){max = this[i];} }
  }
  if (min != max){
    var bucket = new Array(size);
    for (var i = 0; i < size; i++){bucket[i] = new Array();}
    var interpolation = 0;
    for (var i = 0; i < size; i++){
      interpolation = Math.floor(((this[i] - min) / (max - min)) * (size - 1));
      bucket[interpolation].push(this[i]);
    }
    for (var i = 0; i < size; i++){
      if (bucket[i].length > 1){bucket[i].bucketSort();}//遞歸
      for(var j = 0; j < bucket[i].length; j++){this[start++] = bucket[i][j];}
    }
  }
};