一、问题描述
输入:一个最多包含n个正整数的文件,每个数都小于n,其中
并且每个数都不相同。
输出:按生序排序的输入整数的列表。
约束: 1MB的内存空间可用,运算时间10s以内。
二、解决方案
因为每一个数都不相同,我们可以构造一个 N 个比特位的序列,N位这些整数中的最大值,然后将这1 000 0000 个数一一映射到该比特序列中,最后遍历该比特序列的映射关系,就可以得到排序后的序列。
我们来看一个简单的例子
图1-简单排序例子
三、工程实现
在本文中,我们采用C++来实现该算法。我们将这1000 0000 个数存储在一个整形数组中,为了利用好每个比特位,需要用到或和异或的比特为操作,下面是我实现的BitMap的类。
class BitMap{
public:
BitMap(){
this->arr = new int[REQUIRED_SIZE];
}
~BitMap(){
delete[] this->arr;
}
void set(int index){
int bucket = index / RADIX;
int value = this->arr[bucket];
this->arr[bucket] |= (1 << ((index % RADIX) - 1));
}
bool get(int index){
int bucket = index / RADIX;
int value = this->arr[bucket];
return (((value & (1 << ((index % RADIX) - 1))) ^ (1 << ((index % RADIX) - 1))) == 0);
}
private:
int* arr;
const int REQUIRED_SIZE = 312500;
const int RADIX = 32;
};
实现中关键的操作就是
this->arr[bucket] |= (1 << ((index % RADIX) - 1)); // 设置位
return (((value & (1 << ((index % RADIX) - 1))) ^ (1 << ((index % RADIX) - 1))) == 0); //读取位
为了方便理解,还是画个图来解释一下
2.C++实现详细图解
然后就是利用BitMap去排序了,这个比较简单,将值一个个写入到bitmap,然后遍历bitmap,记录index序列就行了,下面是对应的实现。
class Sort{
public:
Sort(){ bt =new BitMap(); }
~Sort(){delete bt; }
void sort(std::vector<int> &arr){
for(std::vector<int>::iterator it = arr.begin(); it != arr.end(); it++){
bt->set(*it);
}
int ctr = 0;
for(int i = 1; i < MAX_INT; i++){
if(bt->get(i)){
arr[ctr++] = i;
}
}
}
private:
const int MAX_INT = 10000000;
BitMap *bt;
};
详细代码见GitHub (https://github.com/vajn/LINUX_DEMO/blob/master/BitMapSort/btsort.cc)
参考
编程珠玑 第2版