桶排序

當待排序的隨機序列密集的分布于一個狹窄區間時,使用計數排序速度比較快,當待排序的隨機序列比較均勻的分布于一個較寬區間時,可以考慮使用桶排序。桶排序的時間復雜度為O(n),空間復雜度也為O(n)

 既然一個待排序的隨機序列比較均勻的分布于一個區間,就很容易散列到各個桶中,假設有 n 個元素比較均勻的散列到 m 個桶中,則每個桶中的元素數目約為 n/m,可以使用普通排序算法對每個桶中的元素排序,排序完畢后再把所有元素復制到最初序列的位置覆蓋原始序列。實際應中n/m 通常很小,可以使用直接插入排序給每個桶中的元素排序,總的時間復雜度為O(n + m*(n/m)2 + n) = O(n2/m + 2n)  = O(n)。如果每個桶的元素用鏈表存儲,鏈表可以用歸并排序,各桶排序完畢后把各個鏈表連接起來就可以了,省去一次復制元素的麻煩,這樣操作的時間復雜度為O(n + m(n/m)log(n/m)) = O(n + nlogk) = O(n)。

以隨機整數為例,桶排序過程如下表。

48 40 66 91 47 68 31 30 29 23 99 35 23 88 88 87

待排序的隨機序列

01      2              3             4        5   6    7  8               9  

桶號

     29 23 23   31 30 35   48 40 47   66 68   88 88 87   91 99  

散列(/10)到各個桶內

     23 23 29   30 31 35   40 47 48   66 68   87 88 88   91 99 

各桶分別排序

23 23 29 30 31 35 40 47 48 66 68 87 88 88 91 99        

最終排序結果


 1 inline unsigned long power2ceil(unsigned long x)
 2 {
 3   --x;
 4   x |= x >> 1;
 5   x |= x >> 2;
 6   x |= x >> 4;
 7   x |= x >> 8;
 8   x |= x >> 16;
 9 //  x |= x >> 32;
10   return ++x;
11 }
12 
13 inline unsigned long hash_bits(unsigned long x)
14 {
15  unsigned long sum = 0;
16  for(; x > 1; x >>= 1)
17    ++sum;
18  return sum;
19 }
20 
21 // non-portable implementation only for unsigned long type
22 template <typename Compare>
23 void bucket_sort(std::vector<unsigned long>& v, Compare cmp)
24 {
25  unsigned long max = *max_element(v.begin(), v.end());  // 見本主頁的計數排序
26  unsigned long min = *min_element(v.begin(), v.end());    // 見本主頁的計數排序
27  unsigned long max_bits = hash_bits(power2ceil(max - min));
28  unsigned long base = hash_bits(power2ceil(v.size()) / 100);
29  unsigned long bins = 1 << base;
30  unsigned long offset = (max_bits <= base ? base >> 7 : max_bits - base);
31  unsigned long pits = 128;
32  typedef std::vector<unsigned long> VECTOR;
33   std::vector<VECTOR> vec(bins + 1);
34  for(VECTOR::size_type i = 0; i < vec.size(); ++i)
35     vec[i].reserve(pits);
36  for(VECTOR::size_type i = 0; i < v.size(); ++i)
37     vec[(v[i] - min) >> offset].push_back(v[i]);
38  for(VECTOR::size_type i = 0; i < vec.size(); ++i)
39    insertion_sort(vec[i].begin(), vec[i].end(), cmp);           // 插入排序見本主頁的快排
40  unsigned long k = 0;
41  for(std::vector<VECTOR>::size_type i = 0; i < vec.size(); ++i)
42    for(VECTOR::size_type j = 0; j < vec[i].size(); ++j)
43      v[k++= vec[i][j];
44 }