电话号码排序问题——位图排序

http://hi.baidu.com/ucoder/blog/item/a213f6a9601492f61e17a2f0.html

电话号码排序问题描述
输入:一个文件,包含n个正整数,每个正整数要小于n,这里n=1000万(7位).这些数都不重复。
输出:以升序排序文件
约束:至多(大概)只有1MB的可用内存,时限10s左右,外存不限制。
-------------------------------------------From《编程珠玑》-------------------------------------------------------
实现方案一:外排序
如果我们将每个号码表示成一个32位整数,那么我们就可以在1MB空间中存储1000*1000/4(本题
都用1000为进制而不是1024) =250000个号码。所以我们可以用
10000000/250000=40个通道的程序。比如,在第一个通道它将0到249999之间的任意整数读到内
存,并(至多)对250000个整数进行排序,然后将它们写到输出文件中,第二个通道是250000到
499999之间的数,依次类推,知道第40个通道。在主存中可以使用的是快排。但是缺点确实,
我们读取整个输入文件40次的代价。对这些程序可调用合并排序方法。

最后实现方案:位图排序
所谓位图表示,举例来说,我们可以使用一个20位的字符串来表示一个小型的小于20的非负整数
。如{1,2,3,5,8,13}表示成如下字符串:
01110100100001000000
第1位表示数字0,在集合中没有0所以这一位为0
第2位表示数字1,在集合中有1所以这一位为1
第3位表示数字2,在集合中有2所以这一位为1
第4位表示数字3,在集合中有3所以这一位为1
第5位表示数字4,在集合中有3所以这一位为0
……
依次表示。

本题中,我们使用1千万位的字符表示这整个文件中的整数。
表示[0,10000000)之间的所有的数。当文件中有这个数时,用1表示,否则为默认值0。这样实际
使用的内存是1000 0000/8=1250000=1.25M。

程序思路:第一阶段关闭所有位,将集合初始化为空。第二阶段读取文件中的每个整数,并打开
相应位。第三阶段检查每个位,如果某个位为1,就写出相应的整数,写入文件中。
//phase 1: initialize set to empty
for i=[0,n)
bit[i]=0;

//phase 2: insert present elements into the set
for each i in the input file 
bit[i]=1

//phase 3: write sorted output
for i=[0,n)
if bit[i]==1
write i on the output file
C源代码(很简练的代码):
#include <stdio.h>

#define BITSPERWORD 32
#define SHIFT 5
#define MASK 0x1F
#define N 10000000
int a[1 + N/BITSPERWORD];

void set(int i) {        a[i>>SHIFT] |= (1<<(i & MASK)); }
void clr(int i) {        a[i>>SHIFT] &= ~(1<<(i & MASK)); }
int test(int i){ return a[i>>SHIFT] &   (1<<(i & MASK)); }

int main()

int i;
for (i = 0; i < N; i++) 
clr(i);
/***Replace above 2 lines with below 3 for word-parallel init
int top = 1 + N/BITSPERWORD;
for (i = 0; i < top; i++)
a[i] = 0;
*/
while (scanf("%d", &i) != EOF)
set(i);
for (i = 0; i < N; i++)
if (test(i))
printf("%d\n", i);
return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值