重复造轮子系列--计数,基数排序

Posted 丹西

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重复造轮子系列--计数,基数排序相关的知识,希望对你有一定的参考价值。

计数,基数的中文读音都一样,这翻译的人还嫌我们计算机不够乱,真的想吐槽。

不管了,毕竟代码还是不一样的。

 

1、计数排序(counter sort):

      通过一个上限来统计集合里的数值(或者其他非数值类型映射的数值),并累计比小于自己(包括)的数值的统计的个数,从而形成排序的索引(也就是前面有多少个小于我的,我的位置就确定了)。

普通计数排序代码:(仍需优化,valuetype默认是整数类型)

 1 template<typename _InIt>
 2 void counter_sort(_InIt first, _InIt last, int k, _InIt result) {
 3     typedef typename iterator_traits<_InIt>::value_type _ValueType;
 4 
 5     vector<_ValueType> v(k, _ValueType(0));
 6     for(_InIt it=first; it!=last; ++it) v[*it]++;
 7 
 8     typename vector<_ValueType>::iterator itx = v.begin()+1;
 9     for(; itx!=v.end() ; ++itx) (*itx) += *(itx-1);
10 
11     for (int i = last - first -1; i>=0; i--) {
12         _ValueType val = *(first+i);
13         *(result + v[val] - 1) = val;
14         v[val]--;
15     }
16 }

2、基数排序(radix sort)

      基数排序道理挺容易理解,算法导论里有图解。不过看到有关ACM的一篇文章里提到MSD(Most Significant Dight)LSD(Least Significant Dight)排序,,

也就是说从那边开始排序效率高,举个整数的例子,3位数,假如每个数最高位都不重复,拿肯定是从数值的最高位排一次就排好序了。不过实际中太多数可能不是这种情况,所以这个只能说跟那个大端小端一样,从那边开始根据具体情况来看。

下面是代码,修改一下计数排序来适配数值的位数变化。

 1 template<typename T>
 2 void print(const vector<T>& v) {
 3     for(vector<int>::const_iterator it=v.begin(); it != v.end(); it++)
 4            cout << *it << " ";
 5         cout << endl;
 6 }
 7 
 8 int decimal_num(int num, int p) {
 9     assert(num >0 && p > 0);
10     return (num%(int)pow(10, p))/(int)pow(10, p-1);
11 }
12 
13 template<typename _InIt>
14 void counter_sort(_InIt first, _InIt last, _InIt result, int k, int p) {
15     typedef typename iterator_traits<_InIt>::value_type _ValueType;
16 
17     vector<_ValueType> v(k, _ValueType(0));
18     for(_InIt it=first; it!=last; ++it) v[decimal_num(*it, p)]++;
19 
20     typename vector<_ValueType>::iterator itx = v.begin()+1;
21     for(; itx!=v.end() ; ++itx) (*itx) += *(itx-1);
22 
23     for (int i = last - first -1; i>=0; i--) {
24         _ValueType val = *(first+i);
25         _ValueType idx = decimal_num(val, p);
26         *(result + v[idx] - 1) = val;
27         v[idx]--;
28     }
29 }
30 
31 template<typename _InIt>
32 void radix_sort(_InIt first, _InIt last, _InIt result, int p) {
33     for (int i=1; i<=p; i++)
34         counter_sort(first, last, result, 10, i);
35 }
36 
37 int main() {
38     int lst[] = {2,5,0,3,2,3,0,3};
39     vector<int> v(lst, lst+8);
40     vector<int> v2(v.size(), 0);
41 
42     counter_sort(v.begin(), v.end(), 6, v2.begin());
43     print(v2);
44 
45     int lst2[] = {329,457,657,839,436,720,355};
46     vector<int> v3(lst2, lst2+7);
47     vector<int> v4(v3.size(), 0);
48 
49     radix_sort(v3.begin(), v3.end(), v4.begin(), 3);
50     print(v4);
51     return 0;
52 }

 

参考:

http://www.acmerblog.com/radix-sorting-5601.html

 

以上是关于重复造轮子系列--计数,基数排序的主要内容,如果未能解决你的问题,请参考以下文章

重复造轮子系列--插入排序和归并排序

重复造轮子系列--dijkstra算法

重复造轮子系列:分布式rpc框架设计_00

不重复造轮子系列JVM学习资源

重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印

排序算法系列:基数排序