国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > PHP > 正文

PHP中實現Bloom Filter算法

2024-05-04 21:55:57
字體:
來源:轉載
供稿:網友

 這篇文章主要介紹了PHP中實現Bloom Filter算法,本文直接給出實現代碼,代碼中給出詳細注釋,Bloom Filter算法介紹等內容,需要的朋友可以參考

 

  1. <?php 
  2.   
  3. /*Bloom Filter算法來去重過濾。 
  4.   
  5.   
  6. 介紹下Bloom Filter的基本處理思路:申請一批空間用于保存0 1信息,再根據一批哈希函數確定元素對應的位置,如果每個哈希函數對應位置的值為全部1,說明此元素存在。相反,如果為0,則要把對應位置的值設置為1。由于不同的元素可能會有相同的哈希值,即同一個位置有可能保存了多個元素的信息,從而導致存在一定的誤判率。 
  7.   
  8. 如果申請空間太小,隨著元素的增多,1會越來越多,各個元素沖突的機會越來越來大,導致誤判率會越來越大。另外哈希函數的選擇及個數上也要平衡好,多個哈希函數雖然可以提供判斷的準確性,但是會降低程序的處理速度,而哈希函數的增加又要求有更多的空間來存儲位置信息。 
  9.   
  10. Bloom-Filter的應用。 
  11.   Bloom-Filter一般用于在大數據量的集合中判定某元素是否存在。例如郵件服務器中的垃圾郵件過濾器。在搜索引擎領域,Bloom-Filter最常用于網絡蜘蛛(Spider)的URL過濾,網絡蜘蛛通常有一個 URL列表,保存著將要下載和已經下載的網頁的URL,網絡蜘蛛下載了一個網頁,從網頁中提取到新的URL后,需要判斷該URL是否已經存在于列表中。此時,Bloom-Filter算法是最好的選擇。  
  12.   比如說,一個象 Yahoo,Hotmail 和 Gmai 那樣的公眾電子郵件(email)提供商,總是需要過濾來自發(fā)送垃圾郵件的人(spamer)的垃圾郵件。一個辦法就是記錄下那些發(fā)垃圾郵件的 email 地址。由于那些發(fā)送者不停地在注冊新的地址,全世界少說也有幾十億個發(fā)垃圾郵件的地址,將他們都存起來則需要大量的網絡服務器。  
  13.   
  14.   布隆過濾器是由巴頓.布隆于一九七零年提出的。它實際上是一個很長的二進制向量和一系列隨機映射函數。我們通過上面的例子來說明起工作原理。 
  15.   
  16.   假定我們存儲一億個電子郵件地址,我們先建立一個十六億二進制(比特),即兩億字節(jié)的向量,然后將這十六億個二進制位全部設置為零。對于每一個電子郵件地址 X,我們用八個不同的隨機數產生器(F1,F2, ...,F8) 產生八個信息指紋(f1, f2, ..., f8)。再用一個隨機數產生器 G 把這八個信息指紋映射到 1 到十六億中的八個自然數 g1, g2, ...,g8。現在我們把這八個位置的二進制位全部設置為一。當我們對這一億個 email 地址都進行這樣的處理后。一個針對這些 email 地址的布隆過濾器就建成了。(見下圖) 現在,讓我們看看如何用布隆過濾器來檢測一個可疑的電子郵件地址 Y 是否在黑名單中。我們用相同的八個隨機數產生器(F1, F2, ..., F8)對這個地址產生八個信息指紋 s1,s2,...,s8,然后將這八個指紋對應到布隆過濾器的八個二進制位,分別是 t1,t2,...,t8。如果 Y 在黑名單中,顯然,t1,t2,..,t8 對應的八個二進制一定是一。這樣在遇到任何在黑名單中的電子郵件地址,我們都能準確地發(fā)現。  
  17.   布隆過濾器決不會漏掉任何一個在黑名單中的可疑地址。但是,它有一條不足之處。也就是它有極小的可能將一個不在黑名單中的電子郵件地址判定為在黑名單中,因為有可能某個好的郵件地址正巧對應八個都被設置成一的二進制位。好在這種可能性很小。我們把它稱為誤識概率。在上面的例子中,誤識概率在萬分之一以下。  
  18.   布隆過濾器的好處在于快速,省空間。但是有一定的誤識別率。常見的補救辦法是在建立一個小的白名單,存儲那些可能別誤判的郵件地址。 
  19.        
  20.        
  21. */ 
  22.   
  23. // 使用php程序來描述上面的算法  
  24.   
  25.   
  26. $set = array(1,2,3,4,5,6); 
  27. // 判斷5是否在$set 中  
  28.   
  29. $bloomFiter = array(0,0,0,0,0,0,0,0,0,0); 
  30.   
  31. // 通過某種算法改變$bloomFiter 中位數組表示集合,這里我們使用簡單的算法,把集合中對應的value 對應到bloom中的位置變成1  
  32.   
  33. // 算法如下  
  34.   
  35.   
  36. foreach($set as $key){ 
  37.       
  38.     $bloomFiter[$key] = 1 ; 
  39.   
  40. var_dump($bloomFiter) ;  
  41.   
  42. //此時 $bloomFiter = array(1,1,1,1,1,1); 
  43.   
  44. //判斷是否在集合中 
  45.   
  46.  if($bloomFiter[9] ==1){ 
  47.      echo '在set 中';  
  48.  }else
  49.      echo '不在set 中' ; 
  50.  } 
  51.    
  52.    
  53.  // 上面只是一個簡單的例子,實際上哈希算法需要好幾個,但另一方面,如果哈希函數的個數少,那么位數組中的0就多 
  54.    
  55.    
  56.  class bloom_filter { 
  57.   
  58.  function __construct($hash_func_num=1, $space_group_num=1) { 
  59.   $max_length = pow(2, 25); 
  60.   $binary = pack('C', 0); 
  61.   
  62.   //1字節(jié)占用8位 
  63.   $this->one_num = 8; 
  64.   
  65.   //默認32m*1 
  66.   $this->space_group_num = $space_group_num
  67.   $this->hash_space_assoc = array(); 
  68.   
  69.   //分配空間 
  70.   for($i=0; $i<$this->space_group_num; $i++){ 
  71.    $this->hash_space_assoc[$i] = str_repeat($binary$max_length); 
  72.   } 
  73.   
  74.   $this->pow_array = array
  75.    0 => 1, 
  76.    1 => 2, 
  77.    2 => 4, 
  78.    3 => 8, 
  79.    4 => 16, 
  80.    5 => 32, 
  81.    6 => 64, 
  82.    7 => 128, 
  83.   ); 
  84.   $this->chr_array = array(); 
  85.   $this->ord_array = array(); 
  86.   for($i=0; $i<256; $i++){ 
  87.    $chr = chr($i); 
  88.    $this->chr_array[$i] = $chr
  89.    $this->ord_array[$chr] = $i
  90.   } 
  91.   
  92.   $this->hash_func_pos = array
  93.    0 => array(0, 7, 1), 
  94.    1 => array(7, 7, 1), 
  95.    2 => array(14, 7, 1), 
  96.    3 => array(21, 7, 1), 
  97.    4 => array(28, 7, 1), 
  98.    5 => array(33, 7, 1), 
  99.    6 => array(17, 7, 1), 
  100.   ); 
  101.   
  102.   $this->write_num = 0; 
  103.   $this->ext_num = 0; 
  104.   
  105.   if(!$hash_func_num){ 
  106.    $this->hash_func_num = count($this->hash_func_pos); 
  107.   } 
  108.   else
  109.    $this->hash_func_num = $hash_func_num
  110.   } 
  111.  } 
  112.   
  113.  function add($key) { 
  114.   $hash_bit_set_num = 0; 
  115. // 離散key 
  116.   $hash_basic = sha1($key); 
  117. //  截取前4位,然后十六進制轉換為十進制 
  118.   $hash_space = hexdec(substr($hash_basic, 0, 4)); 
  119. //  取模 
  120.   $hash_space = $hash_space % $this->space_group_num; 
  121.   
  122.   for($hash_i=0; $hash_i<$this->hash_func_num; $hash_i++){ 
  123.    $hash = hexdec(substr($hash_basic$this->hash_func_pos[$hash_i][0], $this->hash_func_pos[$hash_i][1])); 
  124.    $bit_pos = $hash >> 3; 
  125.    $max = $this->ord_array[$this->hash_space_assoc[$hash_space][$bit_pos]]; 
  126.    $num = $hash - $bit_pos * $this->one_num; 
  127.    $bit_pos_value = ($max >> $num) & 0x01; 
  128.    if(!$bit_pos_value){ 
  129.     $max = $max | $this->pow_array[$num]; 
  130.     $this->hash_space_assoc[$hash_space][$bit_pos] = $this->chr_array[$max]; 
  131.     $this->write_num++; 
  132.    } 
  133.    else
  134.     $hash_bit_set_num++; 
  135.    } 
  136.   } 
  137.   if($hash_bit_set_num == $this->hash_func_num){ 
  138.    $this->ext_num++; 
  139.    return true; 
  140.   } 
  141.   return false; 
  142.  } 
  143.   
  144.  function get_stat() { 
  145.   return array
  146.    'ext_num' => $this->ext_num, 
  147.    'write_num' => $this->write_num, 
  148.   ); 
  149.  } 
  150.   
  151.   
  152. //test 
  153. //取6個哈希值,目前是最多7個 
  154. $hash_func_num = 6; 
  155.   
  156. //分配1個存儲空間,每個空間為32M,理論上是空間越大誤判率越低,注意php.ini中可使用的內存限制 
  157. $space_group_num = 1; 
  158.   
  159. $bf = new bloom_filter($hash_func_num$space_group_num); 
  160.   
  161. $list = array
  162.  'http://test/1'
  163.  'http://test/2'
  164.  'http://test/3'
  165.  'http://test/4'
  166.  'http://test/5'
  167.  'http://test/6'
  168.  'http://test/1'
  169.  'http://test/2'
  170. ); 
  171. foreach($list as $k => $v){ 
  172.   
  173.  if($bf->add($v)){ 
  174.   echo $v"/n"
  175.  } 
  176. print_r($bf->get_stat()); 

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 通道| 资溪县| 华坪县| 肥东县| 新安县| 云霄县| 上虞市| 拉萨市| 永德县| 兰考县| 双鸭山市| 嘉兴市| 锡林浩特市| 启东市| 藁城市| 南乐县| 江达县| 沧州市| 新乡县| 普定县| 库尔勒市| 安仁县| 五华县| 蕉岭县| 洪雅县| 珠海市| 河源市| 盘锦市| 玉田县| 镇康县| 平湖市| 腾冲县| 乐平市| 英吉沙县| 锦屏县| 涿鹿县| 南靖县| 宜城市| 延津县| 正镶白旗| 绍兴市|