[编程珠玑]-第一章:位图/位向量排序

源于编程珠玑-第二版

问题描述:(第一章1.2节)

输入:一个最多包含n个正整数的文件,每个数都小于n, n=10^7,

 输入文件中整数不重复,且无其他数据与该整数相关联。

输出:按升序排列的整数的列表。

约束:最多有大约1MB的内存空间可用,有充足的磁盘存储空间,运行时间最多几分钟


程序设计:

若每个数都使用32位整数来表示,1MB存储空间约可存250000个整数(10^3 X10^3 /32)可遍历输入文件40次来完成排序。在第1趟中读入0~249999间的整数进内存,完成排序后写入到输出文件。

即第i趟读入(i-1)X250000~(iX250000-1)进行排序,输出到文件。

(每趟在内存中进行排序可选择快速排序,不需要额外辅助空间)。

若采用归并排序,则无需对输入文件遍历40次,即不需要选择(i-1)X250000~(iX250000-1)范围内的数进行排序。可以直接读取然后进行排序,输出到多个临时存储文件中,然后通过多次对临时存储文件的整合,合并成一个输出文件。


采用位向量表示集合:

例如使用20位长的字符串来表示一个所有元素都小于20的简单非负整数集合[0,20)。

{1,2,3,5,8,13}

01110100100001000000

本问题中,输入数据限制在相对较小范围内;数据无重复;且无其他关联数据。

可采用1000W个位字符串(10^7)表示输入文件中的数据,当且仅当整数i存在时,第i位字符为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 to the output file

---------------------------------------------------------------------

使用int来完成bit位表示的存储:

int n=10000000;

int[] a= new int[n/32+1];

即将长度n分段开,每段的长度是int的大小(32位)

对于整数 i , i/32 则确定该整数应该所属的int段号

确定下int段号后,可通过 i %32 确定在本int中的哪一位

例如 i =75,则 i/32 =2 , i%32 =11 (和二进制11111相与) 即a[2]的第11号位(二进制从右往左) 标为1 

以位运算表示为 a[i>>5] |= ( 1<<(i&31) ) 

int shift = 5;

int mask= 31;

void SetNum(int i){

a[i>>shift] |= ( 1<<(i&mask) ) ;

}

void output( ){

for p =[0,a.length)

for q=[0,32)

if (a[p] & (1<<q) )==(1<<q)

write p*32+q to output file

}

//将每个int分段位进行判断和输出

(题中的存储空间为约1MB,上述位向量存储约使用1.25MB )


public void test1(){
int n=1000000;
int a[]=new int[(n>>5)+1];
int temp;
  long time1=System.currentTimeMillis();
for(int i=0;i<n;i++){
a[i>>5]|=(1<<(i&31));
}
for(int p=0;p<a.length;p++){
for(int q=0;q<32;q++){
temp=1<<q;
if((a[p]&temp)==temp)
System.out.print((p<<5)+q+",");
}
}
System.out.println();
  System.out.println(System.currentTimeMillis()-time1);
}

/* 测100W 输出耗时66秒.....*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值