理解了基数排序,也就理解了桶排序。
桶排序就是基数排序的一种优化,从MSD开始,即取最高位来排一次序,如果最高位没有重复(意味着没有冲突需要处理),是算法的最佳状态,O(n)。
如果有冲突,就将冲突的元素存放到对应的桶里(代码就是一个链表或者数组或者stl容器),然后对每个桶进行一次插入排序,平均情况的话冲突很小的,桶里的元素的数量就不多,速度很快,
如果冲突集中在几个桶甚至一个桶里,那么就出现了算法的最差情形,也就是O(n^2)的复杂度。
下面是例子代码实现:
1 template<typename _InIt>
2 void bucket_sort(_InIt first, _InIt last, short decimal_bits) {
3 typedef typename iterator_traits<_InIt>::value_type _ValueType;
4 typedef typename vector<_ValueType>::iterator _Iterator;
5
6 int n = last - first;
7 if (n <= 0) return;
8
9 vector< vector<_ValueType> > v(n, vector<_ValueType>());
10 _InIt it = first;
11 for(; it!=last; ++it) {
12 int i = bucket_index(*it, decimal_bits);
13 v[i].insert(v[i].begin(), *it);
14 }
15
16 typename vector< vector<_ValueType> >::iterator ite = v.begin();
17 less_equal<_ValueType> cmp;
18 it = first;
19
20 for(; ite!=v.end(); ++ite) {
21 if (ite->empty()) continue;
22 insert_sort(ite->begin(), ite->end(), cmp);
23 for(_Iterator _it=ite->begin(); _it!=ite->end(); ++_it)
24 *it++ = *_it;
25 }
26 }
上面默认采用了递增排序,如果要递减,就反向迭代并使用greater_equal。
为图简便,这里把元素直接放到输入的容器了。
整个测试程序:
1 #include <iostream>
2 #include <vector>
3 #include <cassert>
4
5 using namespace std;
6
7 template<typename _InIt, typename _Func>
8 void __insert_sort(_InIt first, _InIt last, _Func& Func) {
9 typedef typename iterator_traits<_InIt>::value_type _ValueType;
10
11 for (_InIt it = first+1; it != last+1; ++it) {
12 _ValueType key = *it;
13 _InIt ite = it - 1;
14 for (; (ite - first)>=0 && !Func(*ite, key); --ite)
15 *(ite + 1) = *ite;
16 *(ite + 1) = key;
17 }
18 }
19
20 template<typename _InIt, typename _Func>
21 void insert_sort(_InIt first, _InIt last, _Func& Func) {
22 __insert_sort(first, last-1, Func);
23 }
24
25 int bucket_index(int num, int p) {
26 assert(num >0 && p > 0);
27 int s = 1;
28 while (p-->0) s *= 10;
29 return ((num%s)*10)/s;
30 }
31
32 template<typename _InIt>
33 void bucket_sort(_InIt first, _InIt last, short decimal_bits) {
34 typedef typename iterator_traits<_InIt>::value_type _ValueType;
35 typedef typename vector<_ValueType>::iterator _Iterator;
36
37 int n = last - first;
38 if (n <= 0) return;
39
40 vector< vector<_ValueType> > v(n, vector<_ValueType>());
41 _InIt it = first;
42 for(; it!=last; ++it) {
43 int i = bucket_index(*it, decimal_bits);
44 v[i].insert(v[i].begin(), *it);
45 }
46
47 typename vector< vector<_ValueType> >::iterator ite = v.begin();
48 less_equal<_ValueType> cmp;
49 it = first;
50
51 for(; ite!=v.end(); ++ite) {
52 if (ite->empty()) continue;
53 insert_sort(ite->begin(), ite->end(), cmp);
54 for(_Iterator _it=ite->begin(); _it!=ite->end(); ++_it)
55 *it++ = *_it;
56 }
57 }
58
59 template<typename T>
60 void print(const vector<T>& v) {
61 for(vector<int>::const_iterator it=v.begin(); it != v.end(); it++)
62 cout << *it << " ";
63 cout << endl;
64 }
65
66 int main() {
67 int lst[] = {78,17,39,26,72,94,21,12,23,68};
68 vector<int> v(lst, lst+10);
69
70 bucket_sort(v.begin(), v.end(), 2);
71 print(v);
72
73 return 0;
74 }
写完这些例子,在准备刷难度高一点的算法之前,小小的总结了一下。
这些例子的适用范围都很小,仅供学习使用,比如上面的插入排序,迭代器仅仅对vector有效,如果有自己的数据结构容器,最好是为它实现一个随机访问迭代器。