布隆过滤器在网页去重中的应用

来源:互联网 发布:男士单肩包 知乎 编辑:程序博客网 时间:2024/05/29 17:19
//关于布隆过滤器在URL去重中的应用//问题背景/**假设你想从网上(新浪新闻)去下载一批网页,做信息检索(搜索引擎)的第一步.你已经从网上下载下来了一批网页,并且有这批网页的URL,不过你还有一批需要下载的网页的URL,问题是这样的,如果有些URL已经被下载过了,你就不必要再次下载了,现在让你快速的识别出哪些URL上的是还没被下载的,可以有一定的误差,但是不能超过1%。.**/ //本例中URL初始数量为20万条 ,如果有其它规模的数据,可以将具体参数进行相应更改//测试URL数量为186083条//请使用标准C++进行编译//更多hash函数请登录 泪下的天空//原代码高亮显示#include <string>#include <iostream>#include <assert.h>#include <fstream>#include <time.h>using  namespace std;#define FUNC_NUM 8#define BIT_MAX 3999949 //这是一个素数,why?const int  HASH_SIZE = BIT_MAX / 8  + 1;char    hash[HASH_SIZE];int     strInt[FUNC_NUM];//以下标<<[1-8]>>数字的是字符串散列函数,本程序中我使用了8个散列函数//<<1>>unsigned int RSHash(const std::string& str){   unsigned int b    = 378551;   unsigned int a    = 63689;   unsigned int hash = 0;   for(std::size_t i = 0; i < str.length(); i++)   {      hash = hash * a + str[i];      a    = a * b;   }   return hash;}//<<2>>unsigned int JSHash(const std::string& str){   unsigned int hash = 1315423911;   for(std::size_t i = 0; i < str.length(); i++)   {      hash ^= ((hash << 5) + str[i] + (hash >> 2));   }   return hash;}//<<3>>unsigned int PJWHash(const std::string& str){   unsigned int BitsInUnsignedInt = (unsigned int)(sizeof(unsigned int) * 8);   unsigned int ThreeQuarters     = (unsigned int)((BitsInUnsignedInt  * 3) / 4);   unsigned int OneEighth         = (unsigned int)(BitsInUnsignedInt / 8);   unsigned int HighBits          = (unsigned int)(0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);   unsigned int hash              = 0;   unsigned int test              = 0;   for(std::size_t i = 0; i < str.length(); i++)   {      hash = (hash << OneEighth) + str[i];      if((test = hash & HighBits)  != 0)      {         hash = (( hash ^ (test >> ThreeQuarters)) & (~HighBits));      }   }   return hash;}//<<4>>unsigned int APHash(const std::string& str){   unsigned int hash = 0xAAAAAAAA;   for(std::size_t i = 0; i < str.length(); i++)   {      hash ^= ((i & 1) == 0) ? (  (hash <<  7) ^ str[i] * (hash >> 3)) :                               (~((hash << 11) + (str[i] ^ (hash >> 5))));   }   return hash;}//<<5>>unsigned int BKDRHash(const std::string& str){   unsigned int seed = 131; // 31 131 1313 13131 131313 etc..   unsigned int hash = 0;   for(std::size_t i = 0; i < str.length(); i++)   {      hash = (hash * seed) + str[i];   }   return hash;}//<<6>>unsigned int SDBMHash(const std::string& str){   unsigned int hash = 0;   for(std::size_t i = 0; i < str.length(); i++)   {      hash = str[i] + (hash << 6) + (hash << 16) - hash;   }   return hash;}//<<7>>unsigned int FNVHash(const std::string& str){   const unsigned int fnv_prime = 0x811C9DC5;   unsigned int hash = 0;   for(std::size_t i = 0; i < str.length(); i++)   {      hash *= fnv_prime;      hash ^= str[i];   }   return hash;}//<<8>> unsigned int Hflp(string str){        unsigned int len = str.length();        unsigned int sum = 0;        for(std::size_t i=0;i<len;i++){               sum ^= str[i] << (8*(i%4));        }         return sum & 0x7FFFFFFF; }//更多hash函数请登录 http://jinyun2012.blog.sohu.com//将一个具体的url散列成一组整数void getIntSet(string url , int * set){      set[0] = RSHash(url)   % BIT_MAX;      set[1] = JSHash(url)   % BIT_MAX;      set[2] = PJWHash(url)  % BIT_MAX;      set[3] = APHash(url)   % BIT_MAX;      set[4] = BKDRHash(url) % BIT_MAX;      set[5] = SDBMHash(url) % BIT_MAX;      set[6] = FNVHash(url)  % BIT_MAX;      set[7] = Hflp(url)     % BIT_MAX;}//将每个url映射到hash数组中void shadeHash(string url){      getIntSet(url , strInt);      for(int i=0;i<FUNC_NUM;i++){            int pos = (strInt[i] >> 3);            int mod = strInt[i] & 7;            int val = 1 << (7 - mod);            hash[pos] |= val;      }}//查找url是否存在于url.dat文件中bool find(string url){      getIntSet(url , strInt);      bool res = true;      for(int i=0;i<FUNC_NUM && res == true; i++){            int pos = (strInt[i] >> 3);            int mod = strInt[i] & 7;            int val = 1 << (7 - mod);            res &= (bool)(hash[pos] & val);      }      return res;}int main(int argc, char* argv[]){      ifstream url_in("url.dat");      assert(url_in != NULL);      string url;      int len(0);      time_t con_start = time(NULL);      while(getline(url_in , url)){            len += url.length();            shadeHash(url);      }      time_t con_end = time(NULL);      url_in.close();      //读取文件中测试数据      ifstream test_in("test_url.dat");      assert(test_in);      int count(0) , size(0);      time_t test_start = time(NULL);      while(getline(test_in , url)){            size++;            if(find(url))count++;      }      time_t test_end = time(NULL);      cout<<"测试URL数量:"<<size<<endl;      cout<<"错配URL数量:"<<count<<endl;      cout<<"错配概率   : "<<count * 1.0 / size<<endl << endl;      cout<<"关于优势--->"<<endl;      cout<<"原URL所占存储空间:      "<<len <<" byte"<<endl;      cout<<"程序需要存储空间 :      "<< HASH_SIZE<<" byte"<<endl;      cout<<"空间节约       :      "<< 1.0 - HASH_SIZE * 1.0 / len <<endl;      cout<<"构造hash表所用时间      "<<(con_end - con_start)<<"s"<<endl;      cout<<"测试所用时间            "<<(test_end - test_start)<<"s"<<endl;         return 0;}

原创粉丝点击