总体模块:一次排重模块(基于布隆算法) + 二次排重方案(基于内存数据库)
一次排重
//哈希函数,返回类型为int型
//int型数的总数量[4294967296] (范围大约在正负21亿)
//int类型4个字节,32bits
//排重标志数组的总长度[4294967296/(4*8)=134217728]
//数组过长,编译器编译错误
//拆分成二维数组
//综合考虑空间占用和哈希冲突,选择两个排重标志二维数组
//每个数组占用512MB内存空间
//支持多线程共享
static unsigned int distinctFlgArr1[16][134217728/16];
static unsigned int distinctFlgArr2[16][134217728/16];
//哈希函数
static int hashCode1(std::string &str); //哈希计算1
static int hashCode2(std::string &str); //哈希计算2
static int hashCode3(std::string &str); //哈希计算3
static int hashCode4(std::string &str); //哈希计算4
//参数1:loc即为哈希结果+2147483648
//参数2:mode标识查询哪个排重数组(1或2)
//参数3:引用传递指针,返回要位操作的排重数组元素的地址
//返回值:位操作(位与、位或)需要的参数,该值通过移位操作产生
static unsigned int getFlgInfo(unsigned int loc,int mode,unsigned int* &pFlgVal);
static int getBit(unsigned int* pFlgVal, unsigned int bitOptionVal); //位操作-判断某一位是否为1
static void setBit(unsigned int* pFlgVal, unsigned int bitOptionVal); //位操作-置某一位为1
//一次排重函数
bool judgeDistinct(std::string &str);
//哈希函数定义
int hashCode1(std::string &str){
int h=0;
if(str.length()>0){
for(int i=0;i<str.length();++i){
h=31*h+str.at(i);
}
}
return h;
}
int hashCode2(std::string &str){
int h=0;
if(str.length()>0){
int mode=str.length()>=10?str.length()/5:2;
int num=0;
for(int i=str.length()-1;i>=0;--i){
if((i+1)%mode==0){
++num;
if(num%2==0){ //跳过此位的哈希
continue;
}else{ //增加一位哈希,哈希字符ASCII码值固定为31
h=31*h+31;
}
}
h=31*h+str.at(i);
}
}
return h;
}
int hashCode3(std::string &str) {
int h=0;
if(str.length()>0){
int mode=str.length()>=10?str.length()/5:2;
int num=0;
for(int i=0;i<str.length();++i){
if((i+1)%mode==0){
++num;
if(num%2==0){ //跳过此位的哈希
continue;
}else{ //增加一位哈希,哈希字符ASCII码值固定为31
h=31*h+31;
}
}
h=31*h+str.at(i);
}
}
return h;
}
int hashCode4(std::string &str) {
int h=0;
if(str.length()>0){
int mode=str.length()>=10?str.length()/5:2;
for(int i=0;i<str.length();++i){
if(i%2==0){
h=31*h+(str.at(i)+str.at(str.length()-1-i));
}else{
h=31*h+(str.at(i)-str.at(str.length()-1-i));
}
}
}
return h;
}
//得到数组元素指针 和 位操作参数
//指针引用传递
unsigned int getFlgInfo(unsigned int loc,int mode,unsigned int* &pFlgVal){
unsigned int absSeq = loc / 32; //在一维数组的绝对顺序(第几个元素)
unsigned int relBit = loc % 32; //在这个元素第几位(bit)
unsigned int absSeqX = absSeq / 8388608; //在二维数组的绝对位置(X,Y)
unsigned int absSeqY = absSeq % 8388608;
unsigned int baseVal = (unsigned int)2147483648; //10000000 00000000 00000000 00000000
unsigned int bitOptionVal = baseVal >> relBit;
if(mode==1){
pFlgVal=&distinctFlgArr1[absSeqX][absSeqY];
}
if(mode==2){
pFlgVal=&distinctFlgArr2[absSeqX][absSeqY];
}
return bitOptionVal;
}
//查询是否置位
int getBit(unsigned int* pFlgVal, unsigned int bitOptionVal){
if((*pFlgVal & bitOptionVal) > 0){
return 1; //已经置位
}else{
return 0; //没有置位
}
}
//置位
void setBit(unsigned int* pFlgVal, unsigned int bitOptionVal) {
*pFlgVal |= bitOptionVal; //置位
}
//一次排重函数
bool judgeDistinct(std::string &str){
bool rst=false; //默认不重复
unsigned int hashLoc1=hashCode1(str)+2147483648;
unsigned int hashLoc2=hashCode2(str)+2147483648;
unsigned int hashLoc3=hashCode3(str)+2147483648;
unsigned int hashLoc4=hashCode4(str)+2147483648;
unsigned int* pFlgVal1=NULL;
unsigned int bitOptionVal1=0;
unsigned int* pFlgVal2=NULL;
unsigned int bitOptionVal2=0;
unsigned int* pFlgVal3=NULL;
unsigned int bitOptionVal3=0;
unsigned int* pFlgVal4=NULL;
unsigned int bitOptionVal4=0;
bitOptionVal1=getFlgInfo(hashLoc1,1,pFlgVal1);
bitOptionVal2=getFlgInfo(hashLoc2,2,pFlgVal2);
bitOptionVal3=getFlgInfo(hashLoc3,2,pFlgVal3);
bitOptionVal4=getFlgInfo(hashLoc4,1,pFlgVal4);
//pthread_mutex_lock(&mutex); //加互斥锁
if(getBit(pFlgVal1,bitOptionVal1)==1){
if(getBit(pFlgVal2,bitOptionVal2)==1){
if(getBit(pFlgVal3,bitOptionVal3)==1){
if(getBit(pFlgVal4,bitOptionVal4)==1){
rst=true; //重复
}else{
setBit(pFlgVal4,bitOptionVal4);
}
}else{
setBit(pFlgVal3,bitOptionVal3);
setBit(pFlgVal4,bitOptionVal4);
}
}else{
setBit(pFlgVal2,bitOptionVal2);
setBit(pFlgVal3,bitOptionVal3);
setBit(pFlgVal4,bitOptionVal4);
}
}else{
setBit(pFlgVal1,bitOptionVal1);
setBit(pFlgVal2,bitOptionVal2);
setBit(pFlgVal3,bitOptionVal3);
setBit(pFlgVal4,bitOptionVal4);
}
//pthread_mutex_unlock(&mutex); //释放互斥锁
return rst;
}
===========================================================
二次排重
......到此,,经过两次排重,内存数据库里的记录不重不漏!