方法总结:
补充:数据个数n,与内存大小的换算?
1MB=2^10*8位
2^10~10^3
即10^7个整数占用的内存:
10^7/(10^3)/ (10^3)/8约等于1.25MB
或者:10^7/8/1024/1024≈1MB
补充:10^m与2^n之间的关系?
2^10~10^3
所以:2^31=(2^10)*(2^10)*(2^10)*2
约等于2*(10^3)*(10^3)*(10^3)=2*(10^30)
自己的思考:k趟排序中,每一趟也可以使用位图结构。
如果自己的理解正确,那么数据只要是整数,不用限制数据的范围
因为使用系统的MAX-每个数据就能实现位图排序。
问题:位图排序:一次文件读入内存,读出内存
第一阶段:关闭所有位,置为0;
第二阶段:读入每个整数,打开相应的位,置为1
第三阶段:检查每个位
伪代码:
for i=[0,n)
bit[i]=0;
for each i in the input file
bit[i]=1;
for i=[0,n)
if bit[i]==1
write i on the output file
代码:
bitset<max+1> bit; //初始默认所有二进制位为0 while(scanf("%d",&n)!=EOF) { bit.set(n,1); //将第n位置1 } for(i=0;i<=max+1;i++) { if(bit[i]==1) printf("%d ",i); } return 0; }
k趟算法:需要多次读入文件
时间复杂度:kn
空间复杂度:n/k
对k趟算法中的每一趟算法,满足条件的情况下,可以使用位图排序/快排/堆排序等等排序算法;40个通道的算法:
其他不好的方法:
磁盘的合并排序:运行时间太长, 几天
位图/多路归并排序的实现见:http://blog.csdn.net/v_JULY_v/article/details/6451990
习题
1内存不紧缺,如何排序?答:
1:快排/set容器
int intcomp(int *x,int *y)
{return *x-*y;
}
a[n]
qsort(a,n,sizeof(int),intcomp)
set容器:
2,使用位逻辑运算(与,或,移位)实现位向量?
答:
自己的理解:可以直接使用bitset,对相应位进行设置;
或者 set(i)实现为 a[i]|=1;
clr(i)实现为a[i]&=0;
test(i)实现为:if(a[i]&0x01)
3,实现位图排序,并测试时间?
答:
4,生成一个包含k个整数的文件,要求这些整数是唯一的,并且
在0到n-1之间随机出现,次序也是随机的?
答:
randint(l,u)返回l...u之间的一个随机整数。
for i=[0,n)
x[i]=i;
for i=[0,k)
{
swap(i,randint(i,n-1));
print(x[i]);
}
自己的理解--还可以如下实现:
fori=[1,n)
{
swap(i,rand ()%(i+1));
}
然后仅打印前k个整数
5,只有1MB的内存,但是需要编写的代码有1.25MB,推荐什么算法?
答:
重点 6,如果每个整数最多出现10次,而不是每一个整数至多出现1次,如何改进程序?
答:如果最多出现10次,可以使用半个字节4位统计它出现的次数。
类推:若最多出现20次,使用可以使用5位,统计出现的次数;
若最多出现n次,使用对logn上取整的位数,统计出现的次数;
根据位图法演变解决以下QQ面试题目:作者:Nick Ye(yjf512)出处:(http://www.cnblogs.com/yjf512/)
http://www.cnblogs.com/yjf512/archive/2010/11/04/1868899.html
给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,
如何快速判断这个数是否在那40亿个数当中。
unsign int范围为0~2^32-1(4294967295≈5*10^9)使用位图hash对应5*10^9/8/10^3/10^3 = 625MB.
1. 我们使用625M的字符串。每一位设置为0.
2. 将40亿个unsign int遍历一遍。使用位图法将字符串中的对应位转化为1。
读取“再给一个数i”查看bit[i]是否为1,1则有存在,0则不存在。