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