第一章是磁盘排序问题,面试的时候经常会遇到,百度实习生电话面试时就问了类似的题目,如果一次性能够读入内存,就利用bitmap,否则分多趟分别排序,主要基于归并思想。
题目:1MB的空间里面对10,000,000个整数进行排序,并且每个数都小于10,000,000。
很明显,若用32位int型保存每个数的话,一次只能读入250 000 个号码,若采用一个1千万位的字符串表示每个数,则只需在数字出现的位上置1,那么只需要10000000/(1024* 1024 * 8) = 1.25M。
虽然位图法十分节省时间和空间,但是对于本题有三个限制:
1、输入数据在相对较小的范围内;
2、数据无重复;
3、只有单一整数。
鉴于STL已经封装好了bitset,所以实现如下:
int main()
{
bitset<N> bit;
int n;
while(cin)
{
cin>>n;
bit.set(n, 1);
}
for(int i = 0; i < N; i++)
{
if(bit.at(i) == 1)
cout<<i<<endl;
}
return 0;
}
C语言实现的方法比较晦涩。。。从网上copy来的:
#include <stdio.h>
#define MAX 10000000
#define SHIFT 5
#define MASK 0x1F
#define DIGITS 32
int a[1+MAX/DIGITS];
void set(int n) //将逻辑位置为n的二进制位置为1
{
a[n>>SHIFT] |=(1<<(n&MASK)); //n>>SHIFT右移5位相当于除以32求算字节位置,n&MASK相当于对32取余即求位位置,
}
void clear(int n)
{
a[n>>SHIFT] &=(~(1<<(n&MASK))); //将逻辑位置为n的二进制位置为0
}
int test(int n)
{
return a[n>>SHIFT] & (1<<(n&MASK)); //测试逻辑位置为n的二进制位是否为1
}
int main(int argc, char *argv[])
{
int i,n;
for(i=1;i<=MAX;i++)
{
clear(i);
}
while(scanf("%d",&n)!=EOF)
{
set(n);
}
for(i=1;i<=MAX;i++)
{
if(test(i))
printf("%d ",i);
}
return 0;
}
课后题目:
1、C语言中有qsort(),C++中有sort,STL中的set自动排序。
2、为了测试程序需要产生随机数
就是将n个数利用随机数随机打乱,然后取k个,这里的重点是互不相同的k个数,所以可以利用set保证这一点:
http://www.fookwood.com/archives/605
今天太困,,,明天继续