日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

哈希拓展--布隆过滤器

發(fā)布時間:2023/11/30 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 哈希拓展--布隆过滤器 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、問題概述

?????? 布隆過濾器是由布隆提出來的,是由一個很長的二進(jìn)制序列和一系列的映射函數(shù)組成。主要用于檢測一個元素是否在一個集合中。當(dāng)然在設(shè)計(jì)計(jì)算機(jī)軟件時,我們也經(jīng)常會判斷一個元素是否在一個集合中。比如:在字處理軟件中,需要檢查一個英語單詞是否拼寫正確,(即是否在字典中),在網(wǎng)絡(luò)爬蟲里,這個網(wǎng)站是否被訪問過。最直接的方法就是將元素都存入計(jì)算機(jī)中,遇到一個新元素時,將它和元素進(jìn)行比較即可。一般是用哈希表存儲的,因?yàn)樗牟樵兯俣瓤?#xff0c;就是比較浪費(fèi)空間。集合小的時候存儲效率還好,當(dāng)集合大的時候,存儲效率低的問題就顯現(xiàn)出來了。再比如,對于一個像 Yahoo,Hotmail 和 Gmai 那樣的公眾電子郵件提供商,總是需要過濾來自發(fā)送垃圾郵件的人的垃圾郵件。這時,我們就得記錄那些發(fā)垃圾郵件的Email地址,由于那些發(fā)送者不停地在注冊新的地址,全世界少說也有幾十億個發(fā)垃圾郵件的地址,將他們都存起來則需要大量的網(wǎng)絡(luò)服務(wù)器。如果用哈希表,每存儲一億個email地址,就需要1.6GB 的內(nèi)存,因此存貯幾十億個郵件地址可能需要上百GB的內(nèi)存。除非是超級計(jì)算機(jī),一般服務(wù)器是無法存儲的。所以在這里我們就引入了布隆過濾器來處理這些問題。

二、布隆過濾器的基本思想

?????? 如果想判斷一個元素是不是在一個集合里,一般想到的是將所有元素保存起來,然后通過比較確定。鏈表,樹等等數(shù)據(jù)結(jié)構(gòu)都是這種思路. 但是隨著集合中元素的增加,我們需要的存儲空間越來越大,檢索速度也越來越慢。不過世界上還有一種叫作散列表(又叫哈希表,Hash table)的數(shù)據(jù)結(jié)構(gòu)。它可以通過一個Hash函數(shù)將一個元素映射成一個位陣列(Bit Array)中的一個點(diǎn)。這樣一來,我們只要看看這個點(diǎn)是不是1就知道可以集合中有沒有它了。這就是布隆過濾器的基本思想。


?????? 布隆過濾器是一種空間效率很高的數(shù)據(jù)結(jié)構(gòu)。也可以看做是位圖BitMap的擴(kuò)展(位圖鏈接):

當(dāng)一個元素加入集合中時,通過k個不同的哈希函數(shù)將這個元素映射成一個位數(shù)組的k個點(diǎn),把它們置為1。當(dāng)我們檢測看一個元素存不存在時,只需要看那k個位是否為1就可以了。主要分為兩點(diǎn):

1、如果這k個位中,只要有一個位為0,就說明此元素不在集合中;

2、如果k個位都為1的話,表明此元素可能存在集合中。

第二點(diǎn)又體現(xiàn)了布隆過濾器的一個缺點(diǎn):存在一定的誤判率。但是為了盡可能的降低這種誤判率,我們采用上述多個哈希函數(shù)檢測的方式。經(jīng)研究表明,可將誤判率降低到萬分之一以下。

同時,布隆過濾器的優(yōu)點(diǎn)也是非常顯著的。它的空間效率和查詢時間都遠(yuǎn)遠(yuǎn)超過一般的算法。存儲空間和插入/查詢時間都是常數(shù)(O(k))。

還有重要的一點(diǎn)是,一般情況下,布隆過濾器不支持刪除操作,起初,有人會想到使用計(jì)數(shù)方式將位++或--來刪除元素。但是由于布隆過濾器的誤判,你可能會把錯誤的元素刪除。(下節(jié)我們會分析到這類問題哦)

三、實(shí)現(xiàn)代碼(vs2013)

//HashFunc.h

#pragma once #include<string> #include<iostream> using namespace std;/// @brief BKDR Hash Function /// @detail 本 算法由于在Brian Kernighan與Dennis Ritchie的《The C Programming Language》一書被展示而得 名,是一種簡單快捷的hash算法,也是Java目前采用的字符串的Hash算法(累乘因子為31)。 template<class T> size_t BKDRHash(const T *str) { register size_t hash = 0; while (size_t ch = (size_t)*str++) { hash = hash * 131 + ch; // 也可以乘以31、131、1313、13131、131313.. // 有人說將乘法分解為位運(yùn)算及加減法可以提高效率,如將上式表達(dá)為:hash = hash << 7 + hash << 1 + hash + ch; // 但其實(shí)在Intel平臺上,CPU內(nèi)部對二者的處理效率都是差不多的, // 我分別進(jìn)行了100億次的上述兩種運(yùn)算,發(fā)現(xiàn)二者時間差距基本為0(如果是Debug版,分解成位運(yùn)算后的耗時還要高1/3); // 在ARM這類RISC系統(tǒng)上沒有測試過,由于ARM內(nèi)部使用Booth's Algorithm來模擬32位整數(shù)乘法運(yùn)算,它的效率與乘數(shù)有關(guān): // 當(dāng)乘數(shù)8-31位都為1或0時,需要1個時鐘周期 // 當(dāng)乘數(shù)16-31位都為1或0時,需要2個時鐘周期 // 當(dāng)乘數(shù)24-31位都為1或0時,需要3個時鐘周期 // 否則,需要4個時鐘周期 // 因此,雖然我沒有實(shí)際測試,但是我依然認(rèn)為二者效率上差別不大 } return hash; } /// @brief SDBM Hash Function /// @detail 本算法是由于在開源項(xiàng)目SDBM(一種簡單的數(shù)據(jù)庫引擎)中被應(yīng)用而得名,它與BKDRHash思想一致,只是種子不同而已。 template<class T> size_t SDBMHash(const T *str) { register size_t hash = 0; while (size_t ch = (size_t)*str++) { hash = 65599 * hash + ch; //hash = (size_t)ch + (hash << 6) + (hash << 16) - hash; } return hash; } /// @brief RS Hash Function /// @detail 因Robert Sedgwicks在其《Algorithms in C》一書中展示而得名。 template<class T> size_t RSHash(const T *str) { register size_t hash = 0; size_t magic = 63689; while (size_t ch = (size_t)*str++) { hash = hash * magic + ch; magic *= 378551; } return hash; } /// @brief AP Hash Function /// @detail 由Arash Partow發(fā)明的一種hash算法。 template<class T> size_t APHash(const T *str) { register size_t hash = 0; size_t ch; for (long i = 0; ch = (size_t)*str++; i++) { if ((i & 1) == 0) { hash ^= ((hash << 7) ^ ch ^ (hash >> 3)); } else { hash ^= (~((hash << 11) ^ ch ^ (hash >> 5))); } } return hash; } /// @brief JS Hash Function /// 由Justin Sobel發(fā)明的一種hash算法。 template<class T> size_t JSHash(const T *str) { if(!*str) // 這是由本人添加,以保證空字符串返回哈希值0 return 0; register size_t hash = 1315423911; while (size_t ch = (size_t)*str++) { hash ^= ((hash << 5) + ch + (hash >> 2)); } return hash; } /// @brief DEK Function /// @detail 本算法是由于Donald E. Knuth在《Art Of Computer Programming Volume 3》中展示而得名。 template<class T> size_t DEKHash(const T* str) { if(!*str) // 這是由本人添加,以保證空字符串返回哈希值0 return 0; register size_t hash = 1315423911; while (size_t ch = (size_t)*str++) { hash = ((hash << 5) ^ (hash >> 27)) ^ ch; } return hash; } /// @brief FNV Hash Function /// @detail Unix system系統(tǒng)中使用的一種著名hash算法,后來微軟也在其hash_map中實(shí)現(xiàn)。 template<class T> size_t FNVHash(const T* str) { if(!*str) // 這是由本人添加,以保證空字符串返回哈希值0 return 0; register size_t hash = 2166136261; while (size_t ch = (size_t)*str++) { hash *= 16777619; hash ^= ch; } return hash; } /// @brief DJB Hash Function /// @detail 由Daniel J. Bernstein教授發(fā)明的一種hash算法。 template<class T> size_t DJBHash(const T *str) { if(!*str) // 這是由本人添加,以保證空字符串返回哈希值0 return 0; register size_t hash = 5381; while (size_t ch = (size_t)*str++) { hash += (hash << 5) + ch; } return hash; } /// @brief DJB Hash Function 2 /// @detail 由Daniel J. Bernstein 發(fā)明的另一種hash算法。 template<class T> size_t DJB2Hash(const T *str) { if(!*str) // 這是由本人添加,以保證空字符串返回哈希值0 return 0; register size_t hash = 5381; while (size_t ch = (size_t)*str++) { hash = hash * 33 ^ ch; } return hash; } /// @brief PJW Hash Function /// @detail 本算法是基于AT&T貝爾實(shí)驗(yàn)室的Peter J. Weinberger的論文而發(fā)明的一種hash算法。 template<class T> size_t PJWHash(const T *str) {static const size_t TotalBits = sizeof(size_t) * 8; static const size_t ThreeQuarters = (TotalBits * 3) / 4; static const size_t OneEighth = TotalBits / 8; static const size_t HighBits = ((size_t)-1) << (TotalBits - OneEighth); register size_t hash = 0; size_t magic = 0; while (size_t ch = (size_t)*str++) { hash = (hash << OneEighth) + ch; if ((magic = hash & HighBits) != 0) { hash = ((hash ^ (magic >> ThreeQuarters)) & (~HighBits)); } } return hash; } /// @brief ELF Hash Function /// @detail 由于在Unix的Extended Library Function被附帶而得名的一種hash算法,它其實(shí)就是PJW Hash的變形。 template<class T> size_t ELFHash(const T *str) { static const size_t TotalBits = sizeof(size_t) * 8; static const size_t ThreeQuarters = (TotalBits * 3) / 4; static const size_t OneEighth = TotalBits / 8; static const size_t HighBits = ((size_t)-1) << (TotalBits - OneEighth); register size_t hash = 0; size_t magic = 0; while (size_t ch = (size_t)*str++) { hash = (hash << OneEighth) + ch; if ((magic = hash & HighBits) != 0) { hash ^= (magic >> ThreeQuarters); hash &= ~magic; } } return hash; }

//BloomFilter.h

#pragma once #include<string> #include<iostream> using namespace std; #include"BitMap.h" #include"HashFunc.h" struct _HashFunc1 {size_t operator()(const string& s){return BKDRHash(s.c_str());} };struct _HashFunc2 {size_t operator()(const string& s){return SDBMHash(s.c_str());} };struct _HashFunc3 {size_t operator()(const string& s){return RSHash(s.c_str());} };struct _HashFunc4 {size_t operator()(const string& s){return APHash(s.c_str());} };struct _HashFunc5 {size_t operator()(const string& s){return JSHash(s.c_str());} };template<class K = string, class HashFunc1 = _HashFunc1, class HashFunc2 = _HashFunc2, class HashFunc3 = _HashFunc3, class HashFunc4 = _HashFunc4, class HashFunc5 = _HashFunc5 > class BloomFilter { public:BloomFilter(size_t Num):_bm(Num*5*2),_size(Num*5*2){}void BloomSet(const K& key){size_t Hash1 = HashFunc1()(key)%_size;size_t Hash2 = HashFunc2()(key)%_size;size_t Hash3 = HashFunc3()(key)%_size;size_t Hash4 = HashFunc4()(key)%_size;size_t Hash5 = HashFunc5()(key)%_size;_bm.Set(Hash1);_bm.Set(Hash2);_bm.Set(Hash3);_bm.Set(Hash4);_bm.Set(Hash5);}bool Test(const K& key){size_t Hash1 = HashFunc1()(key)%_size;if(_bm.Test(Hash1) == false){return false;}size_t Hash2 = HashFunc2()(key)%_size;if(_bm.Test(Hash2) == false){return false;}size_t Hash3 = HashFunc3()(key)%_size;if(_bm.Test(Hash3) == false){return false;}size_t Hash4 = HashFunc4()(key)%_size;if(_bm.Test(Hash4) == false){return false;}size_t Hash5 = HashFunc5()(key)%_size;if(_bm.Test(Hash5) == false){return false;}return true;} private:BitMap _bm;size_t _size; };void BloomFilterTest() {BloomFilter<> bm(1024);bm.BloomSet("11111");bm.BloomSet("11110");bm.BloomSet("11112");bm.BloomSet("11113");cout<<bm.Test("11111")<<endl;cout<<bm.Test("11101")<<endl;cout<<bm.Test("11102")<<endl;cout<<bm.Test("11113")<<endl;}

四、運(yùn)行結(jié)果




創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的哈希拓展--布隆过滤器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 色欲av永久无码精品无码蜜桃 | 日本国产精品一区 | 日本一区二区三区在线视频 | 尤物综合网 | 亚洲午夜激情 | 日韩精品成人 | 亚洲女人av | 欧美特一级片 | 日本亚洲色大成网站www久久 | www天天干| 久久综合九色综合欧美狠狠 | 妺妺窝人体色www聚色窝仙踪 | 永久在线 | 久久夜色精品国产噜噜亚洲av | eeuss鲁片一区二区三区在线观看 | 在线观看日本视频 | 师生出轨h灌满了1v1 | 黑人精品无码一区二区三区 | 偷拍欧美另类 | 欧美福利网 | 天狂传说之巴啦啦小魔仙 | 一道本久在线中文字幕 | 日韩欧美手机在线 | 欧美肉大捧一进一出免费视频 | 在线视频1卡二卡三卡 | 中文字幕在线播放视频 | 美女隐私无遮挡网站 | 老妇裸体性激交老太视频 | 日韩毛片视频 | 精品人妻无码在线 | 日本久久成人 | 九九自拍视频 | 欧美啊v | 成年性生交大片免费看 | 国产suv一区二区 | 日本黄色成人 | 成人久久av | 小镇姑娘高清播放视频 | 粉嫩av网址 | 91在线不卡 | 精品自拍偷拍视频 | 欧美性潮喷xxxxx免费视频看 | 蜜臀aⅴ国产精品久久久国产老师 | 久久免费看视频 | 精品日韩在线 | 在线观看国产视频 | 亚洲尹人 | 国产精品啊啊啊 | 网站一级片 | 日韩不卡一二三 | 日韩www在线观看 | 蜜桃免费在线视频 | 手机看片日韩欧美 | 牛牛av在线 | 国产黄色一级片 | 亚洲一区二区免费在线观看 | 成人激情视频在线 | 成人欧美一区二区三区黑人免费 | se日韩| a√天堂资源 | 天堂成人在线视频 | 亚州激情视频 | 无码人妻精品一区二区50 | 亚洲涩色 | 色人阁av| 在线一区观看 | 国产91精品在线观看 | 天堂av免费在线 | 免费黄色在线看 | 舐丝袜脚视频丨vk | 天天操天天摸天天干 | 麻豆免费在线观看视频 | 久久精品黄aa片一区二区三区 | 日韩欧美激情在线 | 农村老妇性真猛 | 奇米av在线 | 爱爱的网站 | 无码人妻精品一区二区三区在线 | 日本另类视频 | chinese精品自拍hd | 中文字幕3区 | 少妇99| 欧美在线二区 | 国产欧美日韩综合精品一区二区三区 | 国产精品人人做人人爽 | 操女人的逼逼 | 日韩av.com | 欧美激情图区 | 黄三级 | 日韩激情网址 | 波多野结衣网站 | 成人小视频在线免费观看 | av大西瓜 | 免费一级全黄少妇性色生活片 | 黑人毛片网站 | 日本一区二区三区在线播放 | 男生和女生一起差差差很痛的视频 | 国产主播在线看 | 久久怡春院|