设为首页 加入收藏

TOP

基数排序的可复用实现(C++11/14/17/20)(三)
2019-07-09 18:10:27 】 浏览:188
Tags:基数 排序 复用 实现 11/14/17/20
中复用来的类:

1 struct Student
2 {
3     char* number;
4     int score;
5 };

其中 number 表示学生学号,是一个十进制下8位数字的C风格字符串, score 的范围为0-660。那么, Student 类的对象就能表示成11个0-9的整数。为了让这个类支持基数排序,我们只需要写一个取相应位上的数的函数就可以了。如果排序的要求是分数从高到低,然后学号从小到大,那么这个函数对象可以实现为:

 1 #include <stdexcept>
 2 
 3 class StudentRadix
 4 {
 5 public:
 6     static constexpr int radix = 10;
 7     static constexpr int pass = 11;
 8     unsigned operator()(const Student& _student, int _pass)
 9     {
10         if (_pass < 8)
11             return _student.number[7 - _pass] - '0';
12         else switch (_pass)
13         {
14         case 8:
15             return 9 - _student.score % 10;
16         case 9:
17             return 9 - _student.score / 10 % 10;
18         case 10:
19             return 9 - _student.score / 100;
20         }
21         throw std::runtime_error("unknown \"pass\" value");
22     }
23 };

因为LSD基数排序是从低位到高位来分组的,所以较早的循环应该取的较次要的位;为了把分数排成降序,所有分数字段上的位都返回被9减去的结果。

同样地,调用处的代码为:

1 std::vector<Student> students;
2 radix_sort(students.begin(), students.end(), StudentRadix::radix, StudentRadix(), StudentRadix::pass);

对于更加简单的类型,比如0-999的整数,调用就更加简单(往往在这种情况下基数排序比时间复杂度为O(nlogn)的排序算法快):

 1 std::vector<int> data;
 2 radix_sort(data.begin(), data.end(), 10, [](int _value, int _pass) {
 3     switch (_pass)
 4     {
 5         case 0: return _value % 10;
 6         case 1: return _value / 10 % 10;
 7         case 2: return _value / 100;
 8     }
 9     throw std::runtime_error();
10 }, 3);

 

最后还要说一下,以上接口和实现都还有优化的空间。对于接口,每一轮循环的基数可以不同,接口中可以加入这种考虑;对于实现,在分组与收集的过程中,每一轮循环,每一个元素都被复制了一次,对于涉及到动态内存的类来说,这是很耗时的,可以将基数排序与表排序结合使用来避免。

文章中如有错误请指正,并欢迎补充。

首页 上一页 1 2 3 下一页 尾页 3/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C++屌屌的观察者模式-同步回调和.. 下一篇BFS(三):双向广度优先搜索

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目