飞道的博客

哈希结构的实现

495人阅读  评论(0)

目录

unordered系列关联式容器

哈希的简介

哈希表闭散列实现

哈希表开散列实现

用哈希表来封装map和set

位图

布隆过滤器与哈希切割

全部代码


unordered系列关联式容器

unordered系列关联式容器有四种,这里主要对unordered_map和unordered_set这两种容器进行介绍

unordered_map

unordered_map是存储<key, value>键值对的关联式容器,其允许通过keys快速的索引到与其对应的value

在内部,unordered_map没有对<kye, value>按照任何特定的顺序排序

unordered_map容器通过key访问单个元素要比map快,但它通常在遍历元素子集的范围迭代方面效率较低

unordered_maps实现了直接访问操作符(operator[]),它允许使用key作为参数直接访问value

unordered_set

unordered_set和unordered_map在性质上差不多,因为底层结构是一致的,都是哈希结构,区别在与,unordered_set不支持[],因为它存储的是key与value相同,所以无需支持[]

哈希的简介

概念

如果构造一种存储结构,通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素

哈希函数有多种,这里采用除留余数法

哈希冲突

比如14和4取模后都是4,而4对应的位置只能存储一个数字,那么就出现了哈希冲突,而解决哈希冲突的常见两种方法有闭散列和开散列

哈希表闭散列实现

闭散列:也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以把key存放到冲突位置中的“下一个” 空位置中去

寻找下一空位置有线性探测和二次探测两种

线性探测

从发生冲突的位置开始,依次向后探测,直到寻找到下一个空位置为止

 二次探测

从发生冲突的位置开始,跨越探测,直到寻找到下一个空位置为止

index是哈希表的下标

首先因为有闭散列和开散列两种,所以采用命名空间的形式来防止命名冲突

 

然后定义一个枚举类型,用来判断该下标的空间的状态,是存在数据,还是删除过数据,或者没有数据,便于插入,删除,及查找数据

封装节点,开始必然为每个下标所在的空间必然为空状态,所以初始化为空状态

 

因为要是除留取余法,必然要是整数,所以还需要借助仿函数来实现

内置类型

string类型

string类型转整形,可以将字符串的每个字母的ASCII码值加起来,但要是只是顺序不同,那总数也会相同,出现哈希冲突,为了尽量减少哈希冲突,就有了下图的方法,其中31是累乘因子

string类型有下列两种写法,任选其一即可

对于其它自定义类型,比如日期,则按照特定方式取整即可 

哈希表同样采用模板的形式实现,另外私有成员有中的_n是有效数据个数,便于后续插入数据扩容使用

 

查找数据

如果表为空,则直接返回nullptr即可

首先用待查找的key模表的长度取模作为待查找的初始下标,然后一直往后查找,同时往后走时,最后别忘了再取模一次,因为可能会存在初始下标空间的前面空间,找不到时,则直接返回nullptr

删除数据

首先先查找数据,找到数据了有效数据就减少一个,然后将那个节点的状态置为删除状态,删除成功返回true即可,没找到就表示删除失败,返回false

插入数据

首先先查找数据,如果存在,就表示待插入的数据已经有了,所以无需再插入,返回false即可

根据有效数据个数,得到负载因子,如果负载因子大于等于0.7则表示需要扩容了,初始没有空间时,也一样需要扩容

负载因子越小,冲突概率越低,效率越高,空间浪费越多

负载因子越大,冲突概率越高,效率越低,空间浪费越少

如果是初始时则开10个空间,其它情况则直接开原来的2倍空间

 

创建一个新表,开辟新空间大小的空间,再将其数据拷贝到新表,然后将新表对象中的vector成员与this对象中的vector成员交换即可

如果不需要开辟新空间

则先将key取模,找到对应的下标,如果有空间,则直接插入数据,没有,则继续往后面找,与find()类似,最后有效数据+1,返回true即可

闭散列最大的缺陷就是空间利用率比较低,这也是哈希的缺陷

哈希表开散列实现

概念

开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中,开散列中每个桶中放的都是发生哈希冲突的元素,如下图

封装节点,其实就是单链表的节点封装

 

私有成员与闭散列一致,同时,还是采用除留去余法,所以会用到仿函数,与上面闭散列一致

查找数据

如果哈希表为空,则直接返回nullptr

找到待查找的数据节点的下标,以及声明一个局部变量来保存这条链的头节点

从头开始往后找,找到了返回节点地址,没找到返回nullptr

删除数据

如果哈希表为空,返回false,表示删除失败

找到待删除数据节点的那条链的头节点

如果找到了,则分为两种情况,如果就是头节点,那就直接头删,否则就中间删除

 

 如果没找到,则继续往后面找,找不到则返回false,表示删除失败

 插入数据

首先先查找数据,如果存在,就表示待插入的数据已经有了,所以无需再插入,返回false即可

 

如果负载因子等于1时,则需要扩容,初始开空间时开10个空间,其余情况开原来的2倍空间

然后将原表的数据按头插拷贝到新表,将原表每条链的表头置空,最后再交换this对象的vector成员与新表的vector成员即可

如果不需要扩容,则直接头插,然后将有效数据个数+1,再返回true即可

为了减少哈希冲突,每次扩容后的空间大小都为素数

  

用哈希表来封装map和set

改善哈希表

因为既要封装map,又要封装set,所以将数据类型从pair类型变为了T类型

迭代器

因为会用到哈希表,所以提前声明一下 

因为要封装map和set,所以多加了一个模板参数KeyOfT,采用了仿函数

因为map和set存储的数据不同,一个是pair<key,value>,一个是key所以对*和对->都要重载

判断相不相等,比较的是节点的地址相不相等

重载++运算符

如果这条链上还有节点,即没有遇到nullptr,则直接往后走即可

如果为nullptr,则从哈希表的下一个元素开始找,比如下图,走完11后,则继续往后面走,下一个元素表头为空,所以就走到了13,不为nullptr,则跳出循环

 

如果是循环自动结束的,即走完整个哈希表了,则直接置nullptr即可

 

如果是break出来的,则直接返回到那个节点,比如上述所说的13

 

拷贝构造

别忘了写一个默认构造函数,因为有了拷贝构造之后,编译器不会默认生成了

这里采用的是头插法,所以顺序会有变化

重载赋值运算符

将实参传给形参时会有一次拷贝构造,所以只需将this对象的两个成员与形参的交换即可

析构函数

从哈希表第一个元素开始销毁节点,直到走完哈希表结束

初始节点

如果哈希表第一个元素的头节点不为nullptr,则它就是初始节点,否则直接返回nullptr的迭代器

结尾节点,即nullptr

重载[]运算符

[]可查找value,也可修改或插入

位图

位图的作用:数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在,比如在一堆数据中找5在不在,数据很多时,可以开辟整形最大值那么大的以bit为单位的空间,然后一个整数对应一个比特位,如果5对应的比特位是1,那就在这堆数据中,是0就不在

1byte=8bit,所以开空间数如下图

将某个bit位置为1

将某个bit位置为0

检查某个bit位是否为1

0为假,非0为真

位图:节省空间,效率高,但只能处理整数

布隆过滤器与哈希切割

概念

布隆过滤器是由布隆在1970年提出的 一种紧凑型的、比较巧妙的概率型数据结构,特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”,它是用多个哈希函数,将一个数据映射到位图结构中。既可以提升查询效率,也可以节省大量的内存空间

作用:用来解决字符串,自定义类型对象在不在的问题

如果采用将字符串转整数,即将字符串的各个字符加起来取模作为下标,那就可能会存在哈希冲突,比如下图中eat和ate

这种方式,判断不在是准确的,比如eat和ate那个位置的比特位为0,则eat肯定不在,只是判断在会存在误判

解决方式

将一个元素用多个哈希函数映射到一个位图中,比如ate,只要三个种有一个bit位为0,则就表示ate不在,降低了误判率

这里以哈希函数中三个不同的哈希函数为例模板参数


  
  1. //hashTable-副本
  2. #pragma once
  3. #include<vector>
  4. template< class K>
  5. struct Hash
  6. {
  7. size_t operator()(const K& key)
  8. {
  9. return key;
  10. }
  11. };
  12. //特化
  13. template<>
  14. struct Hash< string >
  15. {
  16. size_t operator()(const string& s)
  17. {
  18. //BKDR
  19. size_t value = 0;
  20. for ( auto ch : s)
  21. {
  22. value *= 31;
  23. value += ch;
  24. }
  25. return value;
  26. }
  27. };
  28. namespace CloseHash
  29. {
  30. enum Status
  31. {
  32. EXIST,
  33. EMPTY,
  34. DELETE
  35. };
  36. template< class K, class V>
  37. struct HashData
  38. {
  39. pair<K, V> _kv;
  40. Status _status = EMPTY;
  41. };
  42. struct HashStr
  43. {
  44. size_t operator()(const string& s)
  45. {
  46. //BKDR
  47. size_t value = 0;
  48. for ( auto ch : s)
  49. {
  50. value *= 31;
  51. value += ch;
  52. }
  53. return value;
  54. }
  55. };
  56. template< class K, class V, class HashFunc = Hash<K>>
  57. class HashTable
  58. {
  59. public:
  60. bool Erase( const K& key)
  61. {
  62. HashData<K, V>* ret = Find(key);
  63. if (ret == nullptr)
  64. {
  65. return false;
  66. }
  67. else
  68. {
  69. --_n;
  70. ret->_status = DELETE;
  71. return true;
  72. }
  73. }
  74. HashData<K, V>* Find(const K& key)
  75. {
  76. if (_tables. size() == 0)
  77. {
  78. return nullptr;
  79. }
  80. HashFunc hf;
  81. size_t start = hf(key) % _tables. size();
  82. size_t i = 0;
  83. size_t index = start;
  84. //线性探测 or 二次探测
  85. while (_tables[index]._status != EMPTY)
  86. {
  87. if (_tables[index]._kv.first == key && _tables[index]._status == EXIST)
  88. {
  89. return &_tables[index];
  90. }
  91. ++i;
  92. //index = start + i*i;
  93. index = start + i;
  94. index %= _tables. size();
  95. }
  96. return nullptr;
  97. }
  98. bool Insert(const pair<K, V>& kv)
  99. {
  100. HashData<K, V>* ret = Find(kv.first);
  101. if (ret)
  102. {
  103. return false;
  104. }
  105. //负载因子到0.7,就扩容
  106. //负载因子越小,冲突概率越低,效率越高,空间浪费越多
  107. //负载因子越大,冲突概率越高,效率越低,空间浪费越少
  108. if (_tables. size() == 0 || _n * 10 / _tables. size() >= 7)
  109. {
  110. //扩容
  111. size_t newSize = _tables. size() == 0 ? 10 : _tables. size() * 2;
  112. //vector<HashData<K,V>> newTables;
  113. //newTables.resize(newSize);
  114. //遍历原表,把原表中的数据,重新按newSize映射到新表
  115. //for(size_t i = 0;i < _tables.size();++i)
  116. //{
  117. //
  118. //}
  119. //_tables.swap(newTables);
  120. HashTable<K, V, HashFunc> newHT;
  121. newHT._tables. resize(newSize);
  122. for ( size_t i = 0; i < _tables. size(); ++i)
  123. {
  124. if (_tables[i]._status == EXIST)
  125. {
  126. newHT. Insert(_tables[i]._kv);
  127. }
  128. }
  129. _tables. swap(newHT._tables);
  130. }
  131. HashFunc hf;
  132. size_t start = hf(kv.first) % _tables. size();
  133. size_t i = 0;
  134. size_t index = start;
  135. //线性探测 or 二次探测
  136. while (_tables[index]._status == EXIST)
  137. {
  138. ++i;
  139. //index = start + i * i;
  140. index = start + i;
  141. index %= _tables. size();
  142. }
  143. _tables[index]._kv = kv;
  144. _tables[index]._status = EXIST;
  145. ++_n;
  146. return true;
  147. }
  148. private:
  149. vector<HashData<K, V>> _tables;
  150. size_t _n = 0; //有效数据个数
  151. };
  152. void TestHashTable1()
  153. {
  154. //HashTable<int,int,Hash<int>> ht;
  155. HashTable< int, int> ht;
  156. int a[] = { 2, 12, 22, 32, 42, 52, 62 };
  157. for ( auto e : a)
  158. {
  159. ht. Insert( make_pair(e, e));
  160. }
  161. ht. Insert( make_pair( 72, 72));
  162. ht. Insert( make_pair( 72, 72));
  163. ht. Insert( make_pair( -1, -1));
  164. ht. Insert( make_pair( -999, -999));
  165. Hash< int> hs;
  166. cout << hs( 9) << endl;
  167. cout << hs( -9) << endl;
  168. cout << ht. Find( 12) << endl;
  169. ht. Erase( 12);
  170. cout << ht. Find( 12) << endl;
  171. }
  172. struct Date
  173. {
  174. };
  175. struct HashDate
  176. {
  177. size_t operator()(const Date& d)
  178. {
  179. //...
  180. }
  181. };
  182. void TestHashTable2()
  183. {
  184. HashStr hs;
  185. cout << hs( "sort") << endl;
  186. cout << hs( "insert") << endl;
  187. cout << hs( "eat") << endl;
  188. cout << hs( "ate") << endl;
  189. cout << hs( "abcd") << endl;
  190. cout << hs( "aadd") << endl;
  191. HashTable<string, string> ht;
  192. ht. Insert( make_pair( "sort", "排序"));
  193. ht. Insert( make_pair( "string", "字符串"));
  194. //当key是一个定义类型时,需要配置一个仿函数,将key转成整形
  195. HashTable<Date, string, HashDate> htds;
  196. }
  197. }
  198. namespace LinkHash
  199. {
  200. template< class K, class V>
  201. struct HashNode
  202. {
  203. pair<K, V> _kv;
  204. HashNode<K, V>* _next;
  205. HashNode( const pair<K, V>& kv):_kv(kv),_next( nullptr)
  206. {}
  207. };
  208. template< class K, class V, class HashFunc = Hash<K>>
  209. class HashTable
  210. {
  211. typedef HashNode<K, V> Node;
  212. public:
  213. bool Erase(const K& key)
  214. {
  215. if (_tables. empty())
  216. {
  217. return false;
  218. }
  219. HashFunc hf;
  220. size_t index = hf(key) % _tables. size();
  221. Node* prev = nullptr;
  222. Node* cur = _tables[index];
  223. while (cur)
  224. {
  225. if (cur->_kv.first == key)
  226. {
  227. if (prev == nullptr) //头删
  228. {
  229. _tables[index] = cur->_next;
  230. }
  231. else //中间删除
  232. {
  233. prev->_next = cur->_next;
  234. }
  235. --_n;
  236. delete cur;
  237. return true;
  238. }
  239. else
  240. {
  241. prev = cur;
  242. cur = cur->_next;
  243. }
  244. }
  245. return false;
  246. }
  247. Node* Find(const K& key)
  248. {
  249. if (_tables. empty())
  250. {
  251. return nullptr;
  252. }
  253. HashFunc hf;
  254. size_t index = hf(key) % _tables. size();
  255. Node* cur = _tables[index];
  256. while (cur)
  257. {
  258. if (cur->_kv.first == key)
  259. {
  260. return cur;
  261. }
  262. else
  263. {
  264. cur = cur->_next;
  265. }
  266. }
  267. return nullptr;
  268. }
  269. bool Insert(const pair<K, V>& kv)
  270. {
  271. Node* ret = Find(kv.first);
  272. if (ret)
  273. return false;
  274. HashFunc hf;
  275. if (_n == _tables. size())
  276. {
  277. size_t newSize = _tables. size() == 0 ? 10 : _tables. size() * 2;
  278. //...
  279. vector<Node*> newTables;
  280. newTables. resize(newSize);
  281. for ( size_t i = 0; i < _tables. size(); ++i)
  282. {
  283. Node* cur = _tables[i];
  284. while (cur)
  285. {
  286. Node* next = cur->_next;
  287. size_t index = hf(cur->_kv.first) % newTables. size();
  288. //头插
  289. cur->_next = newTables[index];
  290. newTables[index] = cur;
  291. cur = next;
  292. }
  293. _tables[i] = nullptr;
  294. }
  295. _tables. swap(newTables);
  296. }
  297. size_t index = hf(kv.first) % _tables. size();
  298. Node* newnode = new Node(kv);
  299. //头插
  300. newnode->_next = _tables[index];
  301. _tables[index] = newnode;
  302. ++_n;
  303. return true;
  304. }
  305. private:
  306. /*struct Data
  307. {
  308. forward_list<T> _list;
  309. set<T> _rbtree;
  310. size_t len;
  311. };
  312. vector<Data> _table;*/
  313. vector<Node*> _tables;
  314. size_t _n = 0; //有效数据的个数
  315. };
  316. void TestHashTable()
  317. {
  318. int a[] = { 4, 24, 14, 7, 37, 27, 57, 67, 34, 14, 54 };
  319. HashTable< int, int> ht;
  320. for ( auto e : a)
  321. {
  322. ht. Insert( make_pair(e, e));
  323. }
  324. ht. Insert( make_pair( 84, 84));
  325. }
  326. };
  327. //hashTable
  328. #pragma once
  329. #include<vector>
  330. #include<string>
  331. template< class K>
  332. struct Hash
  333. {
  334. size_t operator()(const K& key)
  335. {
  336. return key;
  337. }
  338. };
  339. //特化
  340. template<>
  341. struct Hash< string >
  342. {
  343. size_t operator()(const string& s)
  344. {
  345. //BKDR
  346. size_t value = 0;
  347. for ( auto ch : s)
  348. {
  349. value *= 31;
  350. value += ch;
  351. }
  352. return value;
  353. }
  354. };
  355. namespace CloseHash
  356. {
  357. enum Status
  358. {
  359. EXIST,
  360. EMPTY,
  361. DELETE
  362. };
  363. template< class K, class V>
  364. struct HashData
  365. {
  366. pair<K, V> _kv;
  367. Status _status = EMPTY;
  368. };
  369. //struct HashStr
  370. //{
  371. // size_t operator()(const string& s)
  372. // {
  373. // //BKDR
  374. // size_t value = 0;
  375. // for (auto ch : s)
  376. // {
  377. // value *= 31;
  378. // value += ch;
  379. // }
  380. // return value;
  381. // }
  382. //};
  383. template< class K, class V, class HashFunc = Hash<K>>
  384. class HashTable
  385. {
  386. public:
  387. bool Erase( const K& key)
  388. {
  389. HashData<K, V>* ret = Find(key);
  390. if (ret == nullptr)
  391. {
  392. return false;
  393. }
  394. else
  395. {
  396. --_n;
  397. ret->_status = DELETE;
  398. return true;
  399. }
  400. }
  401. HashData<K, V>* Find(const K& key)
  402. {
  403. if (_tables. size() == 0)
  404. {
  405. return nullptr;
  406. }
  407. HashFunc hf;
  408. size_t start = hf(key) % _tables. size();
  409. size_t i = 0;
  410. size_t index = start;
  411. //线性探测 or 二次探测
  412. while (_tables[index]._status != EMPTY)
  413. {
  414. if (_tables[index]._kv.first == key && _tables[index]._status == EXIST)
  415. {
  416. return &_tables[index];
  417. }
  418. ++i;
  419. //index = start + i*i;
  420. index = start + i;
  421. index %= _tables. size();
  422. }
  423. return nullptr;
  424. }
  425. bool Insert(const pair<K, V>& kv)
  426. {
  427. HashData<K, V>* ret = Find(kv.first);
  428. if (ret)
  429. {
  430. return false;
  431. }
  432. //负载因子到0.7,就扩容
  433. //负载因子越小,冲突概率越低,效率越高,空间浪费越多
  434. //负载因子越大,冲突概率越高,效率越低,空间浪费越少
  435. if (_tables. size() == 0 || _n * 10 / _tables. size() >= 7)
  436. {
  437. //扩容
  438. size_t newSize = _tables. size() == 0 ? 10 : _tables. size() * 2;
  439. //vector<HashData<K,V>> newTables;
  440. //newTables.resize(newSize);
  441. //遍历原表,把原表中的数据,重新按newSize映射到新表
  442. //for(size_t i = 0;i < _tables.size();++i)
  443. //{
  444. //
  445. //}
  446. //_tables.swap(newTables);
  447. HashTable<K, V, HashFunc> newHT;
  448. newHT._tables. resize(newSize);
  449. for ( size_t i = 0; i < _tables. size(); ++i)
  450. {
  451. if (_tables[i]._status == EXIST)
  452. {
  453. newHT. Insert(_tables[i]._kv);
  454. }
  455. }
  456. _tables. swap(newHT._tables);
  457. }
  458. HashFunc hf;
  459. size_t start = hf(kv.first) % _tables. size();
  460. size_t i = 0;
  461. size_t index = start;
  462. //线性探测 or 二次探测
  463. while (_tables[index]._status == EXIST)
  464. {
  465. ++i;
  466. //index = start + i * i;
  467. index = start + i;
  468. index %= _tables. size();
  469. }
  470. _tables[index]._kv = kv;
  471. _tables[index]._status = EXIST;
  472. ++_n;
  473. return true;
  474. }
  475. private:
  476. vector<HashData<K, V>> _tables;
  477. size_t _n = 0; //有效数据个数
  478. };
  479. void TestHashTable1()
  480. {
  481. //HashTable<int,int,Hash<int>> ht;
  482. HashTable< int, int> ht;
  483. int a[] = { 2, 12, 22, 32, 42, 52, 62 };
  484. for ( auto e : a)
  485. {
  486. ht. Insert( make_pair(e, e));
  487. }
  488. ht. Insert( make_pair( 72, 72));
  489. ht. Insert( make_pair( 72, 72));
  490. ht. Insert( make_pair( -1, -1));
  491. ht. Insert( make_pair( -999, -999));
  492. Hash< int> hs;
  493. cout << hs( 9) << endl;
  494. cout << hs( -9) << endl;
  495. cout << ht. Find( 12) << endl;
  496. ht. Erase( 12);
  497. cout << ht. Find( 12) << endl;
  498. }
  499. struct Date
  500. {
  501. };
  502. struct HashDate
  503. {
  504. size_t operator()(const Date& d)
  505. {
  506. //...
  507. }
  508. };
  509. void TestHashTable2()
  510. {
  511. /*HashStr hs;
  512. cout << hs("sort") << endl;
  513. cout << hs("insert") << endl;
  514. cout << hs("eat") << endl;
  515. cout << hs("ate") << endl;
  516. cout << hs("abcd") << endl;
  517. cout << hs("aadd") << endl;*/
  518. HashTable<string, string> ht;
  519. ht. Insert( make_pair( "sort", "排序"));
  520. ht. Insert( make_pair( "string", "字符串"));
  521. //当key是一个定义类型时,需要配置一个仿函数,将key转成整形
  522. HashTable<Date, string, HashDate> htds;
  523. }
  524. }
  525. namespace LinkHash
  526. {
  527. template< class T>
  528. struct HashNode
  529. {
  530. T _data;
  531. HashNode<T>* _next;
  532. HashNode( const T& data) :_data(data), _next( nullptr)
  533. {}
  534. };
  535. template< class K, class T, class KeyOfT, class HashFunc>
  536. class HashTable;
  537. template< class K, class T, class Ref, class Ptr, class KeyOfT, class HashFunc>
  538. struct __HTIterator
  539. {
  540. typedef HashNode<T> Node;
  541. typedef __HTIterator<K, T, Ref, Ptr, KeyOfT, HashFunc> Self;
  542. Node* _node;
  543. HashTable<K, T, KeyOfT, HashFunc>* _pht;
  544. __HTIterator(Node* node,HashTable<K,T,KeyOfT,HashFunc>* pht):_node(node),_pht(pht)
  545. {}
  546. Ref operator*()
  547. {
  548. return _node->_data;
  549. }
  550. Ptr operator->()
  551. {
  552. return &_node->_data;
  553. }
  554. Self& operator++()
  555. {
  556. if (_node->_next)
  557. {
  558. _node = _node->_next;
  559. }
  560. else
  561. {
  562. KeyOfT kot;
  563. HashFunc hf;
  564. size_t index = hf( kot(_node->_data)) % _pht->_tables. size();
  565. ++index;
  566. //找下一个不为空的值
  567. while (index < _pht->_tables. size())
  568. {
  569. if (_pht->_tables[index])
  570. {
  571. break;
  572. }
  573. else
  574. {
  575. ++index;
  576. }
  577. }
  578. //表走完了,都没有找到下一个桶
  579. if (index == _pht->_tables. size())
  580. {
  581. _node = nullptr;
  582. }
  583. else
  584. {
  585. _node = _pht->_tables[index];
  586. }
  587. }
  588. return * this;
  589. }
  590. bool operator!=( const Self& s) const
  591. {
  592. return _node != s._node;
  593. }
  594. bool operator==( const Self& s) const
  595. {
  596. return _node = s._node;
  597. }
  598. };
  599. template< class K, class T, class KeyOfT, class HashFunc>
  600. class HashTable
  601. {
  602. typedef HashNode<T> Node;
  603. template< class K, class T, class Ref, class Ptr, class KeyOfT, class HashFunc>
  604. friend struct __HTIterator;
  605. typedef HashTable<K, T, KeyOfT, HashFunc> self;
  606. public:
  607. typedef __HTIterator<K, T, T&, T*, KeyOfT, HashFunc> iterator;
  608. HashTable()
  609. {}
  610. //显示指定编译器去生成默认构造函数
  611. //HashTable() = default;
  612. HashTable( const self& ht)
  613. {
  614. _tables. resize(ht._tables. size());
  615. for ( size_t i = 0; i < ht._tables. size(); ++i)
  616. {
  617. Node* cur = ht._tables[i];
  618. while (cur)
  619. {
  620. Node* copy = new Node(cur->_data);
  621. copy->_next = _tables[i];
  622. _tables[i] = copy;
  623. cur = cur->_next;
  624. }
  625. }
  626. }
  627. //ht1 = ht2
  628. self& operator=(self copy)
  629. {
  630. swap(_n, copy._n);
  631. _tables. swap(copy._tables);
  632. return * this;
  633. }
  634. ~ HashTable()
  635. {
  636. for ( size_t i = 0; i < _tables. size(); ++i)
  637. {
  638. Node* cur = _tables[i];
  639. while (cur)
  640. {
  641. Node* next = cur->_next;
  642. delete cur;
  643. cur = next;
  644. }
  645. _tables[i] = nullptr;
  646. }
  647. }
  648. iterator begin()
  649. {
  650. for ( size_t i = 0; i < _tables. size(); ++i)
  651. {
  652. if (_tables[i])
  653. {
  654. return iterator(_tables[i], this);
  655. }
  656. }
  657. return end();
  658. }
  659. iterator end()
  660. {
  661. return iterator( nullptr, this);
  662. }
  663. bool Erase(const K& key)
  664. {
  665. if (_tables. empty())
  666. {
  667. return false;
  668. }
  669. HashFunc hf;
  670. size_t index = hf(key) % _tables. size();
  671. Node* prev = nullptr;
  672. Node* cur = _tables[index];
  673. KeyOfT kot;
  674. while (cur)
  675. {
  676. if ( kot(cur->_data) == key)
  677. {
  678. if (prev == nullptr) //头删
  679. {
  680. _tables[index] = cur->_next;
  681. }
  682. else //中间删除
  683. {
  684. prev->_next = cur->_next;
  685. }
  686. --_n;
  687. delete cur;
  688. return true;
  689. }
  690. else
  691. {
  692. prev = cur;
  693. cur = cur->_next;
  694. }
  695. }
  696. return false;
  697. }
  698. iterator Find(const K& key)
  699. {
  700. if (_tables. empty())
  701. {
  702. return end();
  703. }
  704. HashFunc hf;
  705. size_t index = hf(key) % _tables. size();
  706. Node* cur = _tables[index];
  707. KeyOfT kot;
  708. while (cur)
  709. {
  710. if ( kot(cur->_data) == key)
  711. {
  712. return iterator(cur, this);
  713. }
  714. else
  715. {
  716. cur = cur->_next;
  717. }
  718. }
  719. return end();
  720. }
  721. size_t GetNextPrime(size_t num)
  722. {
  723. static const unsigned long __stl_prime_list[ 28] =
  724. {
  725. 53, 97, 193, 389, 769,
  726. 1543, 3079, 6151, 12289, 24593,
  727. 49157, 98317, 196613, 393241, 786433,
  728. 1572869, 3145739, 6291469, 12582917, 25165843,
  729. 50331653, 100663319, 201326611, 402653189, 805306457,
  730. 1610612741, 3221225473, 4294967291
  731. };
  732. for( size_t i = 0;i < 28;++i)
  733. {
  734. if (__stl_prime_list[i] > num)
  735. {
  736. return __stl_prime_list[i];
  737. }
  738. }
  739. return __stl_prime_list[ 27];
  740. }
  741. pair<iterator,bool> Insert(const T& data)
  742. {
  743. KeyOfT kot;
  744. iterator ret = Find( kot(data));
  745. if (ret != end())
  746. return make_pair(ret, false);
  747. HashFunc hf;
  748. //负载因子 == 1时扩容
  749. if (_n == _tables. size())
  750. {
  751. //size_t newSize = _tables.size() == 0 ? 10 : _tables.size() * 2;
  752. //...
  753. size_t newSize = GetNextPrime(_tables. size());
  754. /*if (newSize == _tables.size())
  755. {
  756. break;
  757. }*/
  758. vector<Node*> newTables;
  759. newTables. resize(newSize);
  760. for ( size_t i = 0; i < _tables. size(); ++i)
  761. {
  762. Node* cur = _tables[i];
  763. while (cur)
  764. {
  765. Node* next = cur->_next;
  766. size_t index = hf( kot(cur->_data)) % newTables. size();
  767. //头插
  768. cur->_next = newTables[index];
  769. newTables[index] = cur;
  770. cur = next;
  771. }
  772. _tables[i] = nullptr;
  773. }
  774. _tables. swap(newTables);
  775. }
  776. size_t index = hf( kot(data)) % _tables. size();
  777. Node* newnode = new Node(data);
  778. //头插
  779. newnode->_next = _tables[index];
  780. _tables[index] = newnode;
  781. ++_n;
  782. return make_pair( iterator(newnode, this), false);
  783. }
  784. private:
  785. /*struct Data
  786. {
  787. forward_list<T> _list;
  788. set<T> _rbtree;
  789. size_t len;
  790. };
  791. vector<Data> _table;*/
  792. vector<Node*> _tables;
  793. size_t _n = 0; //有效数据的个数
  794. };
  795. }
  796. //unordered-map
  797. #pragma once
  798. #include"HashTable.h"
  799. namespace bit
  800. {
  801. template< class K, class V, class hash = Hash<K>>
  802. class unordered_map
  803. {
  804. struct MapKeyOfT
  805. {
  806. const K& operator()( const pair<K, V>& kv)
  807. {
  808. return kv.first;
  809. }
  810. };
  811. public:
  812. typedef typename LinkHash::HashTable<K, pair<K, V>, MapKeyOfT, hash>::iterator iterator;
  813. iterator begin()
  814. {
  815. return _ht. begin();
  816. }
  817. iterator end()
  818. {
  819. return _ht. end();
  820. }
  821. V& operator[]( const K& key)
  822. {
  823. auto ret = _ht. Insert( make_pair(key, V()));
  824. return ret.first->second;
  825. }
  826. pair<iterator,bool> insert(const pair<K, V>& kv)
  827. {
  828. return _ht. Insert(kv);
  829. }
  830. private:
  831. LinkHash::HashTable<K, pair<K,V>, MapKeyOfT, hash > _ht;
  832. };
  833. void test_unordered_map()
  834. {
  835. unordered_map<string, string> dict;
  836. dict. insert( make_pair( "sort", "排序"));
  837. dict. insert( make_pair( "string", "字符串"));
  838. dict. insert( make_pair( "map", "地图、映射"));
  839. /*cout << dict["sort"] << endl;
  840. cout << dict["string"] << endl;
  841. cout << dict["map"] << endl;*/
  842. //dict["right"] = "右边";
  843. unordered_map<string, string>::iterator it = dict. begin();
  844. while (it != dict. end())
  845. {
  846. cout << it->first << ":" << it->second << endl;
  847. ++it;
  848. }
  849. cout << endl;
  850. unordered_map<string, string> copy(dict);
  851. for ( auto& kv : copy)
  852. {
  853. cout << kv.first << ":" << kv.second << endl;
  854. }
  855. cout << endl;
  856. }
  857. }
  858. //unordered-set
  859. #pragma once
  860. namespace bit
  861. {
  862. template< class K, class hash = Hash<K>>
  863. class unordered_set
  864. {
  865. struct SetKeyOfT
  866. {
  867. const K& operator()( const K& key)
  868. {
  869. return key;
  870. }
  871. };
  872. public:
  873. typedef typename LinkHash::HashTable<K, K, SetKeyOfT, hash>::iterator iterator;
  874. iterator begin()
  875. {
  876. return _ht. begin();
  877. }
  878. iterator end()
  879. {
  880. return _ht. end();
  881. }
  882. pair<iterator,bool> insert(const K& key)
  883. {
  884. return _ht. Insert(key);
  885. }
  886. private:
  887. LinkHash::HashTable<K, K, SetKeyOfT, hash> _ht;
  888. };
  889. void test_unordered_set()
  890. {
  891. unordered_set< int> us;
  892. us. insert( 4);
  893. us. insert( 14);
  894. us. insert( 34);
  895. us. insert( 7);
  896. us. insert( 24);
  897. us. insert( 17);
  898. unordered_set< int>::iterator it = us. begin();
  899. while (it != us. end())
  900. {
  901. cout << *it << " ";
  902. ++it;
  903. }
  904. cout << endl;
  905. unordered_set<int> uss(us);
  906. unordered_set< int>::iterator It = uss. begin();
  907. while (It != uss. end())
  908. {
  909. cout << *It << " ";
  910. ++It;
  911. }
  912. cout << endl;
  913. /*unordered_set<string> uss;
  914. uss.insert("sort");
  915. uss.insert("hash");*/
  916. /*unordered_set<int> us;
  917. for (size_t i = 0; i < 100; ++i)
  918. {
  919. us.insert(i);
  920. }*/
  921. }
  922. }
  923. //bitSet
  924. #pragma once
  925. #include<vector>
  926. namespace bit
  927. {
  928. template< size_t N>
  929. class bitset
  930. {
  931. public:
  932. bitset()
  933. {
  934. _bits. resize(N / 8 + 1, 0);
  935. }
  936. void set(size_t x)
  937. {
  938. size_t i = x / 8;
  939. size_t j = x % 8;
  940. _bits[i] |= ( 1 << j);
  941. }
  942. void reset(size_t x)
  943. {
  944. size_t i = x / 8;
  945. size_t j = x % 8;
  946. _bits[i] &= (~( 1 << j));
  947. }
  948. bool test(size_t x)
  949. {
  950. size_t i = x / 8;
  951. size_t j = x % 8;
  952. return _bits[i] & ( 1 << j);
  953. }
  954. private:
  955. std::vector< char> _bits;
  956. //std::vector<int> _bits;
  957. };
  958. void test_bitset()
  959. {
  960. bitset<100> bs;
  961. bs. set( 5);
  962. bs. set( 4);
  963. bs. set( 10);
  964. bs. set( 20);
  965. cout << bs. test( 5) << endl;
  966. cout << bs. test( 4) << endl;
  967. cout << bs. test( 10) << endl;
  968. cout << bs. test( 20) << endl;
  969. cout << bs. test( 21) << endl;
  970. cout << bs. test( 6) << endl << endl;
  971. bs. reset( 20);
  972. bs. reset( 10);
  973. bs. reset( 5);
  974. cout << bs. test( 5) << endl;
  975. cout << bs. test( 4) << endl;
  976. cout << bs. test( 10) << endl;
  977. cout << bs. test( 20) << endl;
  978. cout << bs. test( 21) << endl;
  979. cout << bs. test( 6) << endl;
  980. //bitset<0xffffffff> bs;
  981. //bitset<-1> bs;
  982. }
  983. }
  984. template< size_t N>
  985. class TwoBitSet
  986. {
  987. public:
  988. void Set(size_t x)
  989. {
  990. if (!_bs1. test(x) && !_bs2. test(x)) //00 -> 01
  991. {
  992. _bs2. set(x);
  993. }
  994. else if (!_bs1. test(x) && _bs2. test(x)) //01 -> 10
  995. {
  996. _bs1. set(x);
  997. _bs2. reset(x);
  998. }
  999. //10 表示已经出现2次或以上,不用处理
  1000. }
  1001. void PrintOnceNum()
  1002. {
  1003. for ( size_t i = 0; i < N; ++i)
  1004. {
  1005. if (!_bs1. test(i) && _bs2. test(i)) // 01
  1006. {
  1007. cout << i << endl;
  1008. }
  1009. }
  1010. }
  1011. private:
  1012. bit::bitset<N> _bs1;
  1013. bit::bitset<N> _bs2;
  1014. };
  1015. void TestTwoBitSet()
  1016. {
  1017. int a[] = { 99, 0, 4, 50, 33, 44, 2, 5, 99, 0, 50, 99, 50, 2 };
  1018. TwoBitSet< 100> bs;
  1019. for ( auto e : a)
  1020. {
  1021. bs. Set(e);
  1022. }
  1023. bs. PrintOnceNum();
  1024. }
  1025. void TestFindIntersection()
  1026. {
  1027. int a1[] = { 5, 30, 1, 99, 10 };
  1028. int a2[] = { 8, 10, 11, 9, 30, 10, 30 };
  1029. }
  1030. //BloomFilter
  1031. #pragma once
  1032. #include<bitset>
  1033. #include<string>
  1034. #include<time.h>
  1035. struct BKDRHash
  1036. {
  1037. size_t operator()(const string& s)
  1038. {
  1039. //BKDR
  1040. size_t value = 0;
  1041. for ( auto ch : s)
  1042. {
  1043. value *= 3;
  1044. value += ch;
  1045. }
  1046. return value;
  1047. }
  1048. };
  1049. struct APHash
  1050. {
  1051. size_t operator()(const string& s)
  1052. {
  1053. size_t hash = 0;
  1054. for ( long i = 0; i < s. size(); i++)
  1055. {
  1056. if ((i & 1) == 0)
  1057. {
  1058. hash ^= ((hash << 7) ^ s[i] ^ (hash >> 3));
  1059. }
  1060. else
  1061. {
  1062. hash ^= (~((hash << 11) ^ s[i] ^ (hash >> 5)));
  1063. }
  1064. }
  1065. return hash;
  1066. }
  1067. };
  1068. struct DJBHash
  1069. {
  1070. size_t operator()(const string& s)
  1071. {
  1072. size_t hash = 5381;
  1073. for( auto ch : s)
  1074. {
  1075. hash += (hash << 5) + ch;
  1076. }
  1077. return hash;
  1078. }
  1079. };
  1080. template< size_t N,
  1081. size_t X = 8,
  1082. class K = string,
  1083. class HashFunc1 = BKDRHash,
  1084. class HashFunc2 = APHash,
  1085. class HashFunc3 = DJBHash>
  1086. class BloomFilter
  1087. {
  1088. public:
  1089. void Set( const K& key)
  1090. {
  1091. size_t len = X * N;
  1092. size_t index1 = HashFunc1()(key) % len;
  1093. size_t index2 = HashFunc2()(key) % len;
  1094. size_t index3 = HashFunc3()(key) % len;
  1095. cout << index1 << endl;
  1096. cout << index2 << endl;
  1097. cout << index3 << endl << endl;
  1098. _bs. set(index1);
  1099. _bs. set(index2);
  1100. _bs. set(index3);
  1101. }
  1102. bool Test(const K& key)
  1103. {
  1104. size_t len = X * N;
  1105. size_t index1 = HashFunc1()(key) % len;
  1106. if (_bs. test(index1) == false)
  1107. return false;
  1108. size_t index2 = HashFunc2()(key) % len;
  1109. if (_bs. test(index2) == false)
  1110. return false;
  1111. size_t index3 = HashFunc3()(key) % len;
  1112. if (_bs. test(index3) == false)
  1113. return false;
  1114. return true; //存在误判的
  1115. }
  1116. //不支持删除,删除可能会影响其它值。
  1117. void Reset(const K& key);
  1118. private:
  1119. bitset<X* N> _bs;
  1120. };
  1121. void TestBloomFilter1()
  1122. {
  1123. BloomFilter< 100> bm;
  1124. bm. Set( "sort");
  1125. bm. Set( "left");
  1126. bm. Set( "right");
  1127. bm. Set( "eat");
  1128. bm. Set( "ate");
  1129. bm. Set( "https://www.cnblogs.com/-clq/archive/2012/05/31/2528153.html");
  1130. }
  1131. void TestBloomFilter2()
  1132. {
  1133. BloomFilter< 100> bf;
  1134. bf. Set( "张三");
  1135. bf. Set( "李四");
  1136. bf. Set( "牛魔王");
  1137. bf. Set( "红孩儿");
  1138. bf. Set( "eat");
  1139. cout << bf. Test( "张三") << endl;
  1140. cout << bf. Test( "李四") << endl;
  1141. cout << bf. Test( "牛魔王") << endl;
  1142. cout << bf. Test( "红孩儿") << endl;
  1143. cout << bf. Test( "孙悟空") << endl;
  1144. cout << bf. Test( "二郎神") << endl;
  1145. cout << bf. Test( "猪八戒") << endl;
  1146. cout << bf. Test( "ate") << endl;
  1147. //BloomFilter<100> bf;
  1148. srand( time( 0));
  1149. size_t N = 100;
  1150. std::vector<std::string> v1;
  1151. for ( size_t i = 0; i < N; ++i)
  1152. {
  1153. std::string ur1 = "https://www.cnblogs.com/-clq/archive/2012/05/31/2528153.html";
  1154. ur1 += std:: to_string( 1234 + i);
  1155. v1. push_back(ur1);
  1156. }
  1157. for ( auto& str : v1)
  1158. {
  1159. bf. Set(str);
  1160. }
  1161. for ( auto& str : v1)
  1162. {
  1163. cout << bf. Test(str) << endl;
  1164. }
  1165. cout << endl << endl;
  1166. std::vector<std::string> v2;
  1167. for ( size_t i = 0; i < N; ++i)
  1168. {
  1169. std::string ur1 = "https://www.cnblogs.com/-clq/archive/2012/05/31/2528153.html";
  1170. ur1 += std:: to_string( 6789 + i);
  1171. v2. push_back(ur1);
  1172. }
  1173. size_t n2 = 0;
  1174. for ( auto& str : v2)
  1175. {
  1176. if (bf. Test(str))
  1177. {
  1178. ++n2;
  1179. }
  1180. }
  1181. cout << "相似字符串误判率:" << ( double)n2 / ( double)N << endl;
  1182. std::vector<std::string> v3;
  1183. for ( size_t i = 0; i < N; ++i)
  1184. {
  1185. string ur1 = "zhihu.com";
  1186. //std::string ur1 = "https://mail.qq.com/cgi-bin/frame_html?sid=0QvJ6bvfhn3EC1Iw&r=5976c09322eae24513a5ff315428cd86&lang=zh";
  1187. //std::string ur1 = "https://www.sogou.com/tx?query=%E5%88%98%E5%BC%BA%E4%B8%9C%E4%BA%8B%E4%BB%B6%20%E5%A5%B3%E6%96%B9%E7%A7%B0%E8%87%AA%E6%84%BF%E5%8F%91%E7%94%9F%E5%85%B3%E7%B3%BB&hdq=sogou-site-706608cfdbcc1886&ekv=3&ie=utf8&";
  1188. //std::string ur1 = "https://www.sogou.com/sogou?ie=utf8&pid=sogou-wsse-af64b05ee108fa0c&query=%E4%BA%BA%E6%B0%91%E7%BD%91%3A%E5%BE%B7%E4%BA%91%E7%A4%BE%E8%AF%A5%E8%87%AA%E6%88%91%E6%A3%80%E8%A7%86%E4%BA%86";
  1189. ur1 += std:: to_string( rand());
  1190. v3. push_back(ur1);
  1191. }
  1192. size_t n3 = 0;
  1193. for ( auto& str : v3)
  1194. {
  1195. if (bf. Test(str))
  1196. {
  1197. ++n3;
  1198. }
  1199. }
  1200. cout << "不相似字符串误判率:" << ( double)n3 / ( double)N << endl;
  1201. }

设置为1

首先先用三个哈希函数算出对应的下标

再复用前面的位图的函数将其bit位设为1即可 

 

注意:当len越大时,即空间开的越大时,误判率会越低

检查在不在

三个bit位,只要有一个bit位为0,则表示不在

注意:布隆过滤器不支持删除,因为支持删除会消耗很多空间,而且会存在误删,比如上图中的ate和eat,如果删除ate,那就会改变eat中的其中一个bit位

哈希切割

例:给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法和近似算法,这里就要用到哈希切割

注意:如果Ai和Bi都太大,可以考虑换个哈希函数,再切割一次 

全部代码


转载:https://blog.csdn.net/weixin_58867976/article/details/125464703
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场