桶排序(Bucket sort)即箱排序,是計數排序的更新版,它利用了函數的映射關系,高效與否的關鍵就在于這個映射函數的确定。工作的原理是将數組分到有限數量的桶裡,每個桶再個别排序,有可能再使用别的排序算法或是以遞歸方式繼續使用桶排序進行排序。當要被排序的數組内的數值是均勻配置設定的時候,桶排序使用線性時間
。但桶排序并不是比較排序,他不受到
下限的影響。
為了使桶排序更加高效,我們需要做到這兩點:
(1)在額外空間充足的情況下,盡量增大桶的數量
(2)使用的映射函數能夠将輸入的 N 個資料均勻的配置設定到 K 個桶中
同時,對于桶中元素的排序,選擇何種比較排序算法對于性能的影響至關重要。
1. 算法步驟
(1)設定一個定量的數組當作空桶子。
(2)尋訪序列,并且把項目一個一個放到對應的桶子去。
(3)對每個不是空的桶子進行排序。
(4)從不是空的桶子裡把項目再放回原來的序列中。
2. 算法示範
元素分布在桶中:
然後,元素在每個桶中排序:
3. 算法複雜度
最壞時間複雜度:
最優時間複雜度:
平均時間複雜度:
最壞空間複雜度:
4. 代碼實作
(1)Python
def BucketSort(Lst):
Bucket = [0]*(max(Lst)- min(Lst) +1) #建立并初始化桶
for i in range(len(Lst)): #把所有的元素放入桶中,即把對應的元素+1
Bucket[Lst[i]-min(Lst)] += 1
temp = []
for i in range(len(Bucket)): #取出桶中的元素
if Bucket[i] != 0:
temp += [min(Lst) + i] * Bucket[i]
return temp
(2)Java
public class BucketSort implements IArraySort {
private static final InsertSort insertSort = new InsertSort();
@Override
public int[] sort(int[] sourceArray) throws Exception {
// 對 arr 進行拷貝,不改變參數内容
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
return bucketSort(arr, 5);
}
private int[] bucketSort(int[] arr, int bucketSize) throws Exception {
if (arr.length == 0) {
return arr;
}
int minValue = arr[0];
int maxValue = arr[0];
for (int value : arr) {
if (value < minValue) {
minValue = value;
} else if (value > maxValue) {
maxValue = value;
}
}
int bucketCount = (int) Math.floor((maxValue - minValue) / bucketSize) + 1;
int[][] buckets = new int[bucketCount][0];
// 利用映射函數将資料配置設定到各個桶中
for (int i = 0; i < arr.length; i++) {
int index = (int) Math.floor((arr[i] - minValue) / bucketSize);
buckets[index] = arrAppend(buckets[index], arr[i]);
}
int arrIndex = 0;
for (int[] bucket : buckets) {
if (bucket.length <= 0) {
continue;
}
// 對每個桶進行排序,這裡使用了插入排序
bucket = insertSort.sort(bucket);
for (int value : bucket) {
arr[arrIndex++] = value;
}
}
return arr;
}
/**
* 自動擴容,并儲存資料
*
* @param arr
* @param value
*/
private int[] arrAppend(int[] arr, int value) {
arr = Arrays.copyOf(arr, arr.length + 1);
arr[arr.length - 1] = value;
return arr;
}
}
(3)JavaScript
function bucketSort(arr, bucketSize) {
if (arr.length === 0) {
return arr;
}
var i;
var minValue = arr[0];
var maxValue = arr[0];
for (i = 1; i < arr.length; i++) {
if (arr[i] < minValue) {
minValue = arr[i]; // 輸入資料的最小值
} else if (arr[i] > maxValue) {
maxValue = arr[i]; // 輸入資料的最大值
}
}
//桶的初始化
var DEFAULT_BUCKET_SIZE = 5; // 設定桶的預設數量為5
bucketSize = bucketSize || DEFAULT_BUCKET_SIZE;
var bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;
var buckets = new Array(bucketCount);
for (i = 0; i < buckets.length; i++) {
buckets[i] = [];
}
//利用映射函數将資料配置設定到各個桶中
for (i = 0; i < arr.length; i++) {
buckets[Math.floor((arr[i] - minValue) / bucketSize)].push(arr[i]);
}
arr.length = 0;
for (i = 0; i < buckets.length; i++) {
insertionSort(buckets[i]); // 對每個桶進行排序,這裡使用了插入排序
for (var j = 0; j < buckets[i].length; j++) {
arr.push(buckets[i][j]);
}
}
return arr;
}
(4)C++
#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;
}
}
(5)PHP
function bucketSort($arr, $bucketSize = 5)
{
if (count($arr) === 0) {
return $arr;
}
$minValue = $arr[0];
$maxValue = $arr[0];
for ($i = 1; $i < count($arr); $i++) {
if ($arr[$i] < $minValue) {
$minValue = $arr[$i];
} else if ($arr[$i] > $maxValue) {
$maxValue = $arr[$i];
}
}
$bucketCount = floor(($maxValue - $minValue) / $bucketSize) + 1;
$buckets = array();
for ($i = 0; $i < count($buckets); $i++) {
$buckets[$i] = [];
}
for ($i = 0; $i < count($arr); $i++) {
$buckets[floor(($arr[$i] - $minValue) / $bucketSize)][] = $arr[$i];
}
$arr = array();
for ($i = 0; $i < count($buckets); $i++) {
$bucketTmp = $buckets[$i];
sort($bucketTmp);
for ($j = 0; $j < count($bucketTmp); $j++) {
$arr[] = $bucketTmp[$j];
}
}
return $arr;
}
參考來源:http://www.runoob.com/w3cnote/bucket-sort.html
GitHub推薦:https://github.com/hustcc/JS-Sorting-Algorithm/blob/master/9.bucketSort.md
原文位址:https://zh.wikipedia.org/wiki/%E6%A1%B6%E6%8E%92%E5%BA%8F