《演算法導論》——桶排序
阿新 • • 發佈:2018-12-03
《演算法導論》——桶排序
- 桶排序的思想就是把區間[0, 1)劃分成n個相同大小的子區間,每一個區間稱為桶(bucket)。然後,將n個輸入資料分佈到各個桶中去。因為輸入數均勻且獨立均勻分佈在[0, 1)上,所以一般不會有很多數落在一個桶中的情況。為得到結果,先對各個桶中的數進行排序,然後按次序把各個桶中的元素列出來即可。時間複雜度O(n).
- 在桶排序演算法中,假設輸入的是一個含n個元素的陣列A,且每個元素滿足0≤A[i]<1。另外,還需要一個輔助陣列B[0…n-1]來存放連結串列(桶),並假設可以用某種機制來維護這些表
虛擬碼
c++程式碼
#include "iostream" #include "stdlib.h" using namespace std; struct Node { double value; struct Node *next; }; void BUCKET_SORT(double* array, int len) { int count = 0; Node *bucket = new Node [len] ; //開闢了一塊連續的儲存len個Node(頭節點)的陣列 for (int i = 0; i < len; i++) //初始化頭 { bucket[i].value = 0; bucket[i].next = NULL; } for (int j = 0; j < len; j++) { Node *insert = new Node; insert->value = array[j]; insert->next = NULL; int temp = array[j] * 10; if (bucket[temp].next == NULL) //連結串列中只有頭節點 { bucket[temp].next = insert; //直接插入後 } else //有多個節點,排序插入 { Node *q = &bucket[temp]; //頭節點 Node *p = bucket[temp].next; while (p!= NULL &&( p->value <= array[j])) { p = p->next; q = q->next; } q->next = insert; insert->next = p; } } for (int k = 0; k < len; k++) { Node *p = bucket[k].next; while (p != NULL) { array[count++] = p->value; p = p->next; } } } void main() { double a[] = { 0.12, 0.13, 0.45, 0.53, 0.65, 0.48, 0.34, 0.45 }; int length = sizeof(a) / sizeof(a[0]); BUCKET_SORT(a, length); for (int i = 0; i < length; i++) { cout << a[i] << " "; } cout << endl; system("pause"); }
桶排序也可以拓展至整數部分。
轉載
3. 桶排序在海量資料中的應用
一年的全國高考考生人數為500 萬,分數使用標準分,最低100 ,最高900 ,沒有小數,你把這500 萬元素的陣列排個序。
分析:對500W資料排序,如果基於比較的先進排序,平均比較次數為O(5000000*log5000000)≈1.112億。但是我們發現,這些資料都有特殊的條件: 100=<score<=900。那麼我們就可以考慮桶排序這樣一個“投機取巧”的辦法、讓其在毫秒級別就完成500萬排序。
方法:建立801(900-100)個桶。將每個考生的分數丟進f(score)=score-100的桶中。這個過程從頭到尾遍歷一遍資料只需要500W次。然後根據桶號大小依次將桶中數值輸出,即可以得到一個有序的序列。而且可以很容易的得到100分有**人,501分有*人。
實際上,桶排序對資料的條件有特殊要求,如果上面的分數不是從100-900,而是從0-2億,那麼分配2億個桶顯然是不可能的。所以桶排序有其侷限性,適合元素值集合並不大的情況。