基数排序模板(基数排序,C++模板)
算法的理论学习可右转Creeper_LKF大佬的洛谷日报
一个优化算法理论时间复杂度的实例点这里
另一个实例点这里
时间复杂度\(O(n)\),算常数的话要乘位长。
蒟蒻参考了Creeper_LKF大佬的模板,并在通用性上面稍微提升了一点。可以兼容所有存储整数的基本类型,以及在此基础上构建的结构体类型(多关键字排序时,优先级高的关键字默认需要在结构体中靠后)。
函数原型
template<typename T>
void Radixsort(T*fst,T*lst,T*buf,int*op)
T即为待排序的类型名,fst lst为首尾指针(和sort一样),buf为缓冲区指针,op为操作列表。
\(op[i]\)提供类型的第\(i\)个字节的比较方式,具体来说有\(5\)种取值。
\(-1\):该字节不是排序的关键字。
\(0\):以该字节为基准从小到大排序。
\(1\):以该字节为基准从大到小排序。
\(2\):以该字节为基准从小到大排序,且该字节的最高位是有符号整形的符号位。
\(3\):以该字节为基准从大到小排序,且该字节的最高位是有符号整形的符号位。
例如,对int从小到大排序,则应将\(\{0,0,0,2\}\)传入\(op\)。
对结构体unsigned int,int以前一个为关键字从大到小排序,则代码大致写成
Radixsort(a,a+n,buf,new int[8]{1,1,1,1,-1,-1,-1,-1});
对长度为\(n\)的int数组排序效率对比如下:(STL不吸氧是真的布星)
方式&n=10^6,不开\text{O2}&n=5*10^6,不开\text{O2}&n=5*10^6,开\text{O2}&n=10^7,开\text{O2}\\
\text{Radixsort}&\text{20ms}&\text{120ms}&\text{60ms}&\text{120ms}\\
\text{std::sort}&\text{200+ms}&\text{1100+ms}&\text{320+ms}&\text{680+ms}\\
\text{std::stable_sort}&\text{210+ms}&\text{1200+ms}&\text{410+ms}&\text{860+ms}
\end{matrix}\]
然而,Radixsort的运行时间与待排序类型的关键字位长总和成正比(upd:蒟蒻目测和总位长也有关,猜测是因为访问步长增加导致缓存刷新次数增加。例如,对long long排序大约是对int排序的三倍时间)。
而std::sort受此的影响小多了。当总位长在\(10\)位以上时,开O2以后两者的差距很小了。所以综合实现难度方面,int多关键字和long long等用开O2的std::sort就够了。
至于实数类型,Radixsort不能直接资磁。double是\(8\)位的用std::sort就好了。至于如果是在想从小到大排float的话,必须膜改一下数组,将所有的负实数强行除了符号位都按位取反以后,传入\(\{0,0,0,2\}\),最后还要还原回来,实在是太麻烦了。
#include<bits/stdc++.h>
#define UC unsigned char
using namespace std;
template<typename T>
void Radixsort(T*fst,T*lst,T*buf,int*op){
static int b[0x100];
int Len=lst-fst,Sz=sizeof(T),at=0,i,j;
UC*bgn,*end,tmp;
for(i=0;i<Sz;++i){
if(op[i]==-1)continue;
bgn=(UC*)fst+i;end=(UC*)lst+i;
tmp=((op[i]&1)?0xff:0)^((op[i]&2)?0x80:0);
memset(b,0,sizeof(b));
for(UC*it=bgn;it!=end;it+=Sz)++b[tmp^*it];
for(j=1;j<0x100;++j)b[j]+=b[j-1];
for(UC*it=end;it!=bgn;buf[--b[tmp^*(it-=Sz)]]=*--lst);
lst=buf+Len;swap(fst,buf);at^=1;
}
if(at)memcpy(buf,fst,Sz*Len);
}
有没有觉得很好实现呢?比什么后缀排序不知道好写到哪里去了
这样实现很简短,但常数没有卡到极限,b桶数组的初始化部分可以强行展开出来并行计算。
基数排序模板(基数排序,C++模板)的更多相关文章
- Django(4)html模板继承、模板导入、分页实现
1.获取所有请求信息 导入模块:from django.core.handlers.wsgi import WSGIRequest request.environ:包含所有的请求信息,可以打印看一下, ...
- [Reprint] C++函数模板与类模板实例解析
这篇文章主要介绍了C++函数模板与类模板,需要的朋友可以参考下 本文针对C++函数模板与类模板进行了较为详尽的实例解析,有助于帮助读者加深对C++函数模板与类模板的理解.具体内容如下: 泛型编程( ...
- C++ Primer 学习笔记_76_模板与泛型编程 --模板定义[续]
模板与泛型编程 --模板定义[续] 四.模板类型形參 类型形參由keywordclass或 typename后接说明符构成.在模板形參表中,这两个keyword具有同样的含义,都指出后面所接的名字表示 ...
- 织梦CMS(dedecms)栏目属性及系统封面模板、列表模板、文章模板区别和路径设置解答
问题一:(织梦"栏目管理"的"常规选项"中3个栏目属性分析?) 织梦CMS的栏目属性分成三种, -->最终列表栏目 -->频道封面 -->外部 ...
- (转)DEDECMS模板原理、模板标签学习 - .Little Hann
本文,小瀚想和大家一起来学习一下DEDECMS中目前所使用的模板技术的原理: 什么是编译式模板.解释式模板,它们的区别是什么? 模板标签有哪些种类,它们的区别是什么,都应用在哪些场景? 学习模板的机制 ...
- C++ Primer 学习笔记_84_模板与泛型编程 --模板特化
模板与泛型编程 --模板特化 引言: 我们并不总是能够写出对全部可能被实例化的类型都最合适的模板.某些情况下,通用模板定义对于某个类型可能是全然错误的,通用模板定义或许不能编译或者做错误的事情;另外一 ...
- Django模板-分离的模板
上一篇Django模板-在视图中使用模板最后的问题,我们需要把数据和展现分离开. 你可能首先考虑把模板保存在文件系统的某个位置并用 Python 内建的文件操作函数来读取文件内容. 假设文件保存在 E ...
- C++ Primer 学习笔记_85_模板与泛型编程 --模板特化[续]
模板与泛型编程 --模板特化[续] 三.特化成员而不特化类 除了特化整个模板之外,还能够仅仅特化push和pop成员.我们将特化push成员以复制字符数组,而且特化pop成员以释放该副本使用的内存: ...
- C++ Primer 学习笔记_75_模板与泛型编程 --模板定义
模板与泛型编程 --模板定义 引言: 所谓泛型程序就是以独立于不论什么特定类型的方式编写代码.使用泛型程序时,我们须要提供详细程序实例所操作的类型或值. 模板是泛型编程的基础.使用模板时能够无须了解模 ...
- C++ Primer 学习笔记_76_模板和泛型编程 --模板定义[继续]
模板和泛型编程 --模板定义[续] 四.模板类型形參 类型形參由keywordclass或 typename后接说明符构成.在模板形參表中,这两个keyword具有同样的含义,都指出后面所接的名字表示 ...
随机推荐
- Git - 常见错误与解决方案
1.windows使用git时出现:warning: LF will be replaced by CRLF 分析: windows中的换行符为 CRLF, 而在linux下的换行符为LF,所以在执行 ...
- JQuery/JS select标签动态设置选中值、设置禁止选择 button按钮禁止点击 select获取选中值
//**1.设置选中值:(根据索引确定选中值)**// var osel=document.getElementById("selID"); //得到select的ID var o ...
- Bootstrap知识记录:排版样式
---恢复内容开始--- 一.页面排版Bootstrap 提供了一些常规设计好的页面排版的样式供开发者使用.1.页面主体Bootstrap 将全局font-size 设置为14px,line-heig ...
- 5 Http请求中文乱码处理
java 乱码分很多种,这里主要研究解决http请求中出现乱码的情况. http请求出现中文乱码的主要原因:发送方与接收方编码不一致,服务器默认支持的编码与web应用不一致,如:tomcat 是国外程 ...
- Azure系列1.1.2 —— 用于 IntelliJ 的 Azure 工具包的登录说明
(文中大部分内容(95%)Azure官网上有,我只是把我自己实际操作中遇到的问题在这里阐述一下.) 先决条件 若要完成文章中的步骤,需要安装用于 IntelliJ 的 Azure 工具包,该工具包需要 ...
- 给普通用户添加root权限
>>提君博客原创 http://www.cnblogs.com/tijun/ << 第一步,以root用户查看/etc/sudoers [root@ltt2 hadoop] ...
- Day 4-11 re正则表达式
正则表达式就是字符串的匹配规则,在多数编程语言里都有相应的支持,python里对应的模块是re '.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行 '^' ...
- js中的call、apply、bind
在js中每个函数都包含两个非继承而来的方法:call()和apply() call和apply的作用都是在特定的作用域中将函数绑定到另外一个对象上去运行,即可以用来重新定义函数的执行环境,两者仅在定义 ...
- 配置Google Gmail分类和过滤器
简单的记两笔. 首先点击右上角的⚙️里面选择settings. 选择Filters and Blocked Addresses 在这个页面可以选择 create a new filter创建一个新的过 ...
- DAY02、正式介绍python
一.编程语言介绍(***) 1.1.机器语言:直接用计算机能理解的二进制指令编写程序,直接控制硬件 1.2.汇编语言:用英文标签取代二进制指令编写程序,本质也是直接控制硬件 1.3.高级语言:用人类能 ...