比快排还快的排序
ltc2010/12/12软件综合 IP:浙江
这种排序叫倍增排序,用于对正整数排序,负整数的话可以先都加上一个大的正数再用这种排序,它是基于寻址来排序的,不像快排是基于比较的,倍增排序的速度比快速排序快,是稳定的,不会退化到O(n^2),其时间复杂度为O(n+sqrt(m))(此处m指这些正整数的最大值,用dword类型时取2^32-1,n指待排序数的个数),空间复杂度也是一样,怎么样?是不是比O(n*Logn)快?它的原理和计数排序相似,但排序用的指标不同,它是用a[i]和sqrt(m)的余数、商作为指标,为了加快运行速度,用位运算计算商和余数。
一下是pascal源代码:
const
max=65535;//这边的max就相当于sqrt(m),max一定要(11....11)形式的二进制数,这样才可以用and来求余,提高速度。
var
i,n:longint;
a,b:array[1..1000000]of longint;
m,d:array[0..max+1]of longint;
begin
readln(n);
for i:=1 to n do
begin
read(a[ i]);
inc(m[1+a[ i] and max]);//此时的m表示余数a[ i] mod (max+1)为的数有几个,a[ i] and max=a[ i] mod (max+1)
inc(d[1+a[ i] shr 16]);//此时的d表示商为a[ i] div (max+1)的数有几个,a[ i] shr 16=a[ i] div (max+1)
end;
for i:=1 to max+1 do
begin
inc(m[ i],m[i-1]);//此时的m表示余数小于i(因为前面有加1,所以这里是小于)的数字的个数
inc(d[ i],d[i-1]);//此时的d表示商小于i(因为前面有加1,所以这里是小于)的数字的个数
end;
for i:=1 to n do//这边是按照余数排序
begin
inc(m[a[ i] and max]);//设t=a[ i]and max,这里表示余数为t的数应该放在的地址,因为前面累加之后,m[ t]已经表示余数小于t的数字有多少个,所以当有数字的余数为t时,应从t+1个位置开始放置在b数组,inc(m[ t])表示放置第几个余数为t的数字的地址。
b[m[a[ i] and max]]:=a[ i];
end;
for i:=1 to n do//这边基于已经按照余数排好序的数据再按照商排序
begin
inc(d[b[ i] shr 16]);//设t=a[ i]shr 16,这里表示商为t的数应该放在的地址,因为前面累加之后,d[t]已经表示商小于t的数字有多少个,所以当有数字的商为t时,应从t+1个位置开始放置在a数组,inc(m[ t])表示放置第几个商为t的数字的地址。
a[d[b[ i] shr 16]]:=b[ i];
end;
for i:=1 to n-1 do write(a[ i],' ');
write(a[n]);
end.
来自:计算机科学 / 软件综合
15
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
ltc 作者
14年1个月前 IP:未同步
268919
与其他排序的比较
快速排序 时间复杂度O(n*logn)         空间复杂度O(n*logn)
基数排序 时间复杂度O(n+m)            空间复杂度O(n+m)
倍增排序 时间复杂度O(n+sqrt(m))   空间复杂度O(n+sqrt(m))
虽然m是常数,但是在大多数情况下m较大,故这样写
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltc作者
14年1个月前 IP:未同步
268922
为什么a [ i ]会变成a
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltc作者
14年1个月前 IP:未同步
268923
由于空格会变成?
不保留缩进了
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltc作者
14年1个月前 IP:未同步
268924
实测结果下次再发
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltc作者
14年1个月前 IP:未同步
269348
没人给个评价?
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltc作者
14年1个月前 IP:未同步
269746
上快排和倍增排序的实测结果
用清澄测的
1-5个点   n=1000
6-10个点  n=10000
11-15个点 n=100000
16-20个点 n=1000000
21-25个点 n=10000000
数据为longint类型随机数据
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltc作者
14年1个月前 IP:未同步
269752
1.jpg
2.jpg
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltc作者
14年1个月前 IP:未同步
269787
在大多数情况下,你认为longint类型不够用?
很多排序的题目用-2^31+1~2^31-1完全够用
要用到高精度的,在OI中估计n不会太大吧(其实我也是OIer)
而且你把这个和基数排序或者计数排序比较一下,就会发现其中的优点
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ltc作者
14年1个月前 IP:未同步
269788
高精度的话比较不就要O(n)了???
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
ltc
学者 笔友
文章
40
回复
271
学术分
1
2010/07/24注册,6年11个月前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}