当前位置:   article > 正文

【C++数据结构】哈希表HashMap与HashSet_c++ hashset

c++ hashset

目录

1. 前言 

2. 哈希表原理

3. 源码实现

4. 测试代码

5. 结尾


1. 前言 

        当前的存储结构本质上只有两种:数组、链表。数组支持随机访问,访问速度极快,哈希表就是利用这一点。

2. 哈希表原理

        ①哈希表的底层是数组,数组是通过下标索引访问的,那哈希表就要生成一个索引,为每一个元素分配唯一的索引,而生成这个索引的工具就叫做“哈希函数”,每一个存放数据的位置叫做“桶”。

        ②数组中的每一个元素以键值对key-value形式存在,索引就是通过用哈希函数将key转化为索引。至于怎么转化,这里举一个例子,假设数组容量为16,这里有一个key值为100的元素,那么哈希函数可以直接用 key % 16即100 % 16 = 4来计算,得到的结果4就是这个索引。当插入一个新的元素时,如果其索引位置上已有元素,那么就引入一个新的问题,哈希冲突

        ③哈希冲突的解决办法,这里只列举我代码实现的方法,也是教科书上的办法:当哈希冲突时,后来元素的索引需要一直增加1,即一直往后移动,直到找到空的位置为止。当插入一个新的元素后,如果容量已满,需要即时扩充容量,否则在下一次哈希冲突寻找空位置时会造成死循环。

3. 源码实现

①为了增加遍历哈希容器元素的方便性,我这里为每一个元素增加双向链表作为存储容器,遍历时就遍历这双向链表。

②代码已与C++11中的std::unordered_map和std::unordered_set作一定的兼容。

③代码支持C++03标准,可不必使用C++11以上版本,代码已在VS2005和GCC 4.1中编译通过。

 

头文件:HashTable.h

  1. #ifndef HASH_TABLE_H
  2. #define HASH_TABLE_H
  3. #include <utility>
  4. #include <cmath>
  5. #include <string>
  6. #ifdef __GNUC__
  7. #pragma GCC diagnostic push
  8. #pragma GCC diagnostic ignored "-Wshift-count-overflow"
  9. #elif defined(Clang)
  10. #pragma clang diagnostic push
  11. #pragma clang diagnostic ignored "-Wshift-count-overflow"
  12. #elif defined(_MSC_VER)
  13. #pragma warning(push)
  14. #pragma warning(disable:4293)
  15. #endif
  16. #if __cplusplus >= 201703L
  17. #define null nullptr
  18. #define CONSTEXPR constexpr
  19. #define CXX14_CONSTEXPR constexpr
  20. #define CXX17_CONSTEXPR constexpr
  21. #elif __cplusplus >= 201402L
  22. #define null nullptr
  23. #define CONSTEXPR constexpr
  24. #define CXX14_CONSTEXPR constexpr
  25. #define CXX17_CONSTEXPR
  26. #elif __cplusplus >= 201103L
  27. #define null nullptr
  28. #define CONSTEXPR constexpr
  29. #define CXX14_CONSTEXPR
  30. #define CXX17_CONSTEXPR
  31. #else
  32. #define null 0
  33. #define CONSTEXPR
  34. #define CXX14_CONSTEXPR
  35. #define CXX17_CONSTEXPR
  36. #endif
  37. typedef unsigned long HashType;
  38. template<unsigned long _ByteCount>
  39. HashType _Hash(const void *__ptr, unsigned long __len, unsigned long __seed);
  40. template<>
  41. HashType _Hash<32>(const void *__ptr, unsigned long __len, unsigned long __seed)
  42. {
  43. const unsigned int __m = 0x5bd1e995;
  44. const int __r = 24;
  45. HashType __h = __seed ^ __len;
  46. const unsigned char *__data = static_cast<const unsigned char *>(__ptr);
  47. while(__len >= 4)
  48. {
  49. unsigned int __k = *reinterpret_cast<const unsigned int *>(__data);
  50. __k *= __m;
  51. __k ^= __k >> __r;
  52. __k *= __m;
  53. __h *= __m;
  54. __h ^= __k;
  55. __data += 4;
  56. __len -= 4;
  57. }
  58. switch(__len)
  59. {
  60. case 3:
  61. __h ^= __data[2] << 16;
  62. case 2:
  63. __h ^= __data[1] << 8;
  64. case 1:
  65. __h ^= __data[0];
  66. __h *= __m;
  67. };
  68. __h ^= __h >> 13;
  69. __h *= __m;
  70. __h ^= __h >> 15;
  71. return __h;
  72. }
  73. template<>
  74. HashType _Hash<64>(const void *__ptr, unsigned long __len, unsigned long __seed)
  75. {
  76. const unsigned int __m = 0x5bd1e995;
  77. const int __r = 24;
  78. unsigned int __h1 = __seed ^ __len;
  79. unsigned int __h2 = 0;
  80. const unsigned int * __data = static_cast<const unsigned int *>(__ptr);
  81. while(__len >= 8)
  82. {
  83. unsigned int __k1 = *__data++;
  84. __k1 *= __m;
  85. __k1 ^= __k1 >> __r;
  86. __k1 *= __m;
  87. __h1 *= __m;
  88. __h1 ^= __k1;
  89. __len -= 4;
  90. unsigned int __k2 = *__data++;
  91. __k2 *= __m;
  92. __k2 ^= __k2 >> __r;
  93. __k2 *= __m;
  94. __h2 *= __m;
  95. __h2 ^= __k2;
  96. __len -= 4;
  97. }
  98. if(__len >= 4)
  99. {
  100. unsigned int __k1 = *__data++;
  101. __k1 *= __m;
  102. __k1 ^= __k1 >> __r;
  103. __k1 *= __m;
  104. __h1 *= __m;
  105. __h1 ^= __k1;
  106. __len -= 4;
  107. }
  108. switch(__len)
  109. {
  110. case 3:
  111. __h2 ^= (reinterpret_cast<const unsigned char*>(__data))[2] << 16;
  112. case 2:
  113. __h2 ^= (reinterpret_cast<const unsigned char*>(__data))[1] << 8;
  114. case 1:
  115. __h2 ^= (reinterpret_cast<const unsigned char*>(__data))[0];
  116. __h2 *= __m;
  117. };
  118. __h1 ^= __h2 >> 18;
  119. __h1 *= __m;
  120. __h2 ^= __h1 >> 22;
  121. __h2 *= __m;
  122. __h1 ^= __h2 >> 17;
  123. __h1 *= __m;
  124. __h2 ^= __h1 >> 19;
  125. __h2 *= __m;
  126. HashType __h = __h1;
  127. __h = (__h << 32) | __h2;
  128. return __h;
  129. }
  130. template<unsigned long _ByteCount>
  131. HashType _Hash(const void *__ptr, unsigned long __len);
  132. template<>
  133. HashType _Hash<32>(const void *__ptr, unsigned long __len)
  134. { return _Hash<32>(__ptr, __len, 97); }
  135. template<>
  136. HashType _Hash<64>(const void *__ptr, unsigned long __len)
  137. { return _Hash<64>(__ptr, __len, 0xEE6B27EB); }
  138. template<typename _Tp>
  139. struct Hash
  140. {
  141. HashType operator()(const _Tp &_h) const
  142. { return _h.Hash(); }
  143. };
  144. #define HASH_SPECIALIZED(type) \
  145. template<> \
  146. struct Hash<type> \
  147. { \
  148. HashType operator()(const type &c) const \
  149. { return static_cast<HashType>(c); } \
  150. };
  151. HASH_SPECIALIZED(char)
  152. HASH_SPECIALIZED(unsigned char)
  153. HASH_SPECIALIZED(short)
  154. HASH_SPECIALIZED(unsigned short)
  155. HASH_SPECIALIZED(int)
  156. HASH_SPECIALIZED(unsigned int)
  157. HASH_SPECIALIZED(long)
  158. HASH_SPECIALIZED(unsigned long)
  159. HASH_SPECIALIZED(long long)
  160. HASH_SPECIALIZED(unsigned long long)
  161. template<>
  162. struct Hash<std::string>
  163. {
  164. HashType operator()(const std::string &_s) const
  165. { return _Hash<sizeof(HashType)>(_s.c_str(), _s.size()); }
  166. };
  167. template<typename _Tp>
  168. struct Hash<_Tp *>
  169. {
  170. HashType operator()(const _Tp *_h) const
  171. { return reinterpret_cast<HashType>(_h); }
  172. };
  173. template<typename _Tp>
  174. struct Equal
  175. {
  176. bool operator()(const _Tp &_1, const _Tp &_2) const
  177. { return _1 == _2; }
  178. };
  179. template<typename _Key,
  180. typename _Value,
  181. typename _Hash = Hash<_Key>,
  182. typename _EqualTo = Equal<_Key>
  183. >
  184. class HashTable
  185. {
  186. private:
  187. struct NodeType
  188. {
  189. NodeType(const _Key &k, const _Value &v)
  190. : key(k), value(v), next(null), prev(null)
  191. { }
  192. #if __plusplus >= 201103L
  193. NodeType(const _Key &k, _Value &&v)
  194. : key(k), value(std::move(v)), next(null), prev(null)
  195. { }
  196. #endif
  197. const _Key key;
  198. _Value value;
  199. NodeType *next;
  200. NodeType *prev;
  201. };
  202. public:
  203. class const_iterator;
  204. class iterator
  205. {
  206. private:
  207. friend class HashTable;
  208. friend class const_iterator;
  209. NodeType *_M_data;
  210. public:
  211. iterator(NodeType *__v = null) : _M_data(__v) { }
  212. iterator operator++()
  213. { return iterator(_M_data = _M_data->next); }
  214. iterator operator++(int)
  215. {
  216. iterator __ret(_M_data);
  217. _M_data = _M_data->next;
  218. return __ret;
  219. }
  220. bool operator==(const iterator &__it) const
  221. { return _M_data == __it._M_data; }
  222. bool operator!=(const iterator &__it) const
  223. { return _M_data != __it._M_data; }
  224. _Value& operator*()
  225. { return _M_data->value; }
  226. _Value* operator->()
  227. { return &_M_data->value; }
  228. };
  229. class const_iterator
  230. {
  231. private:
  232. friend class HashTable;
  233. const NodeType *_M_data;
  234. public:
  235. const_iterator(const NodeType *__v = null) : _M_data(__v) { }
  236. const_iterator(const iterator &__i) : _M_data(__i._M_data) { }
  237. const_iterator operator++()
  238. { return const_iterator(_M_data = _M_data->next); }
  239. const_iterator operator++(int)
  240. {
  241. const_iterator __ret(_M_data);
  242. _M_data = _M_data->next;
  243. return __ret;
  244. }
  245. bool operator==(const const_iterator &__it) const
  246. { return _M_data == __it._M_data; }
  247. bool operator!=(const const_iterator &__it) const
  248. { return _M_data != __it._M_data; }
  249. const _Value& operator*()
  250. { return _M_data->value; }
  251. const _Value* operator->()
  252. { return &_M_data->value; }
  253. };
  254. public:
  255. typedef unsigned long size_type;
  256. public:
  257. HashTable()
  258. : _M_capacity(0), _M_count(0), _M_head(null), _M_tail(null), _M_data(null)
  259. { _M_rehash(1, 0); }
  260. HashTable(size_type __bkts)
  261. : _M_capacity(0), _M_count(0), _M_head(null), _M_tail(null), _M_data(null)
  262. { _M_rehash(__bkts, 0); }
  263. HashTable(const HashTable &__ht)
  264. : _M_capacity(0), _M_count(0), _M_head(null), _M_tail(null), _M_data(null)
  265. { this->operator=(__ht); }
  266. #if __cplusplus >= 201103L
  267. HashTable(HashTable &&__ht)
  268. : _M_capacity(0), _M_count(0), _M_head(null), _M_tail(null), _M_data(null)
  269. { swap(__ht); }
  270. #endif
  271. ~HashTable()
  272. {
  273. clear();
  274. delete[] _M_data;
  275. }
  276. void clear()
  277. {
  278. if(_M_count == 0)
  279. {
  280. return;
  281. }
  282. for(size_type __i = 0; __i < _M_capacity; ++__i)
  283. {
  284. if(_M_data[__i])
  285. {
  286. delete _M_data[__i];
  287. _M_data[__i] = null;
  288. }
  289. }
  290. _M_count = 0;
  291. _M_head = _M_tail = null;
  292. }
  293. bool empty() const
  294. { return size() == 0; }
  295. size_type size() const
  296. { return _M_count; }
  297. size_type max_size() const
  298. { return _M_capacity; }
  299. size_type bucket_count() const
  300. { return max_size(); }
  301. size_type bucket_size(size_type) const
  302. { return 1; }
  303. iterator begin()
  304. { return iterator(_M_head); }
  305. const_iterator begin() const
  306. { return const_iterator(_M_head); }
  307. const_iterator cbegin() const
  308. { return begin(); }
  309. iterator end()
  310. { return iterator(null); }
  311. const_iterator end() const
  312. { return const_iterator(null); }
  313. const_iterator cend() const
  314. { return const_iterator(null); }
  315. std::pair<iterator, bool> insert(const _Key &__k, const _Value &__v)
  316. { return _M_insert(__k, __v); }
  317. #if __cplusplus >= 201103L
  318. std::pair<iterator, bool> insert(const _Key &__k, _Value &&__v)
  319. { return _M_insert(__k, std::move(__v)); }
  320. #endif
  321. const_iterator find(const _Key &__k) const
  322. { return _M_find_node(__k); }
  323. iterator find(const _Key &__k)
  324. { return iterator(const_cast<NodeType *>(_M_find_node(__k)._M_data)); }
  325. void rehash(size_type __s)
  326. { _M_rehash(__s, 0); }
  327. _Value& at(const _Key &__k, const _Value &__v)
  328. { return _M_find_and_insert(__k, __v)._M_data->value; }
  329. #if __cplusplus >= 201103L
  330. _Value& at(const _Key &__k, _Value &&__v)
  331. { return _M_find_and_insert(__k, std::move(__v))._M_data->value; }
  332. #endif
  333. void erase(const _Key &__k)
  334. {
  335. const_iterator __beg = _M_find_node(__k);
  336. const_iterator __end = __beg;
  337. _M_erase(__beg, ++__end);
  338. }
  339. void erase(const_iterator __beg, const_iterator __end)
  340. { _M_erase(__beg, __end); }
  341. void swap(HashTable &__ht)
  342. {
  343. std::swap<size_type>(_M_capacity, __ht._M_capacity);
  344. std::swap<size_type>(_M_count, __ht._M_count);
  345. std::swap<NodeType *>(_M_head, __ht._M_head);
  346. std::swap<NodeType *>(_M_tail, __ht._M_tail);
  347. std::swap<NodeType **>(_M_data, __ht._M_data);
  348. }
  349. HashTable& operator=(const HashTable &__ht)
  350. {
  351. clear();
  352. rehash(__ht._M_capacity);
  353. for(size_type __i = 0; __i < __ht._M_capacity; ++__i)
  354. {
  355. NodeType *__node = __ht._M_data[__i];
  356. if(__node)
  357. {
  358. _M_insert(_M_data[__i] = new NodeType(__node->key, __node->value));
  359. }
  360. }
  361. return *this;
  362. }
  363. private:
  364. std::pair<iterator, bool> _M_insert(const _Key &__k, const _Value &__v)
  365. {
  366. if(_M_capacity - _M_count <= 1)
  367. {
  368. _M_rehash(_M_capacity * 2);
  369. }
  370. _Hash __hash;
  371. HashType __code = __hash(__k);
  372. _EqualTo __e;
  373. size_type __index = _S_bucket_index(__code, _M_capacity);
  374. NodeType *__node = null;
  375. while(_M_data[__index])
  376. {
  377. __node = _M_data[__index];
  378. if(__e(__node->key, __k))
  379. {
  380. return std::pair<iterator, bool>(iterator(__node), false);
  381. }
  382. __index = _M_inc(__index, _M_capacity);
  383. }
  384. __node = new NodeType(__k, __v);
  385. _M_data[__index] = __node;
  386. return std::pair<iterator, bool>(_M_insert(__node), true);
  387. }
  388. #if __cplusplus >= 201103L
  389. std::pair<iterator, bool> _M_insert(const _Key &__k, _Value &&__v)
  390. {
  391. if(_M_capacity - _M_count <= 1)
  392. {
  393. _M_rehash(_M_capacity * 2);
  394. }
  395. _Hash __hash;
  396. HashType __code = __hash(__k);
  397. _EqualTo __e;
  398. size_type __index = _S_bucket_index(__code, _M_capacity);
  399. NodeType *__node = null;
  400. while(_M_data[__index])
  401. {
  402. __node = _M_data[__index];
  403. if(__e(__node->key, __k))
  404. {
  405. return std::pair<iterator, bool>(iterator(__node), false);
  406. }
  407. __index = _M_inc(__index, _M_capacity);
  408. }
  409. __node = new NodeType(__k, std::move(__v));
  410. _M_data[__index] = __node;
  411. return std::pair<iterator, bool>(_M_insert(__node), true);
  412. }
  413. #endif
  414. iterator _M_find_and_insert(const _Key &__k, const _Value &__v)
  415. {
  416. const_iterator __f = _M_find_node(__k);
  417. return __f == cend()
  418. ? _M_insert(__k, __v).first
  419. : iterator(const_cast<NodeType *>(__f._M_data));
  420. }
  421. #if __cplusplus >= 201103L
  422. iterator _M_find_and_insert(const _Key &__k, _Value &&__v)
  423. {
  424. const_iterator __f = _M_find_node(__k);
  425. return __f == cend()
  426. ? _M_insert(__k, std::move(__v)).first
  427. : iterator(const_cast<NodeType *>(__f._M_data));
  428. }
  429. #endif
  430. static CXX14_CONSTEXPR size_type _M_inc(size_type __s, size_type __max)
  431. { return ++__s >= __max ? 0 : __s; }
  432. static CXX14_CONSTEXPR size_type _S_bucket_index(size_type __code, size_type __bkt_count)
  433. { return __code % __bkt_count; }
  434. static CXX14_CONSTEXPR size_type _S_clp2(size_type __n)
  435. {
  436. size_type __x = __n;
  437. __x = __x - 1;
  438. __x = __x | (__x >> 1);
  439. __x = __x | (__x >> 2);
  440. __x = __x | (__x >> 4);
  441. __x = __x | (__x >> 8);
  442. __x = __x | (__x >> 16);
  443. if CXX17_CONSTEXPR (sizeof(size_type) >= 8)
  444. {
  445. __x = __x | (__x >> 32);
  446. }
  447. return __x + 1;
  448. }
  449. static CXX14_CONSTEXPR bool _S_is_prime(size_type __n)
  450. {
  451. if (__n <= 3)
  452. {
  453. return __n > 1;
  454. }
  455. if (__n % 6 != 1 && __n % 6 != 5)
  456. {
  457. return false;
  458. }
  459. size_type __s = static_cast<size_type>(::sqrt(double(__n)));
  460. for (size_type __i = 5; __i <= __s; __i += 6)
  461. {
  462. if (__n % __i == 0 || __n % (__i + 2) == 0)
  463. {
  464. return false;
  465. }
  466. }
  467. return true;
  468. }
  469. static CXX14_CONSTEXPR size_type _S_next_bucket(size_type __n)
  470. {
  471. if(__n <= 1)
  472. {
  473. return 1;
  474. }
  475. if(__n == 2 || __n == 3)
  476. {
  477. return __n;
  478. }
  479. __n = _S_clp2(__n) - 1;
  480. while(!_S_is_prime(__n))
  481. { __n -= 2; }
  482. return __n;
  483. }
  484. void _M_rehash(size_type __bkts, size_type __its = 1)
  485. {
  486. __bkts = _S_next_bucket(__bkts);
  487. while(_M_count + __its > __bkts)
  488. {
  489. __bkts = _S_next_bucket(__bkts << 1);
  490. }
  491. NodeType **__tmp = new NodeType*[__bkts];
  492. for(size_type i = 0; i < __bkts; ++i)
  493. {
  494. __tmp[i] = null;
  495. }
  496. _Hash __hash;
  497. for(iterator __it = begin(); __it != end(); ++__it)
  498. {
  499. NodeType *__node = __it._M_data;
  500. size_type __index = _S_bucket_index(__hash(__node->key), __bkts);
  501. while(__tmp[__index])
  502. {
  503. __index = _M_inc(__index, __bkts);
  504. }
  505. __tmp[__index] = __node;
  506. }
  507. delete[] _M_data;
  508. _M_data = __tmp;
  509. _M_capacity = __bkts;
  510. }
  511. const_iterator _M_find_node(const _Key &key) const
  512. {
  513. _Hash __hash;
  514. HashType __code = __hash(key);
  515. _EqualTo __e;
  516. NodeType *__node = null;
  517. size_type __index = _S_bucket_index(__code, _M_capacity);
  518. while(_M_data[__index])
  519. {
  520. __node = _M_data[__index];
  521. if(__e(key, __node->key))
  522. {
  523. return const_iterator(__node);
  524. }
  525. __index = _M_inc(__index, _M_capacity);
  526. }
  527. return const_iterator(null);
  528. }
  529. iterator _M_insert(NodeType *__n)
  530. {
  531. if(!_M_head)
  532. {
  533. _M_head = _M_tail = __n;
  534. }
  535. else
  536. {
  537. _M_tail->next = __n;
  538. __n->prev = _M_tail;
  539. _M_tail = __n;
  540. }
  541. ++_M_count;
  542. return iterator(__n);
  543. }
  544. void _M_erase(const_iterator __beg, const_iterator __end)
  545. {
  546. while(__beg != __end)
  547. {
  548. _M_erase((__beg++)._M_data);
  549. }
  550. }
  551. void _M_erase(const NodeType *__node)
  552. {
  553. if(!__node)
  554. {
  555. return;
  556. }
  557. _Hash __hash;
  558. HashType __code = __hash(__node->key);
  559. _EqualTo __e;
  560. size_type __index = _S_bucket_index(__code, _M_capacity);
  561. while(_M_data[__index])
  562. {
  563. const NodeType *__n = _M_data[__index];
  564. if(__e(__n->key, __node->key))
  565. {
  566. _M_data[__index] = null;
  567. break;
  568. }
  569. __index = _M_inc(__index, _M_capacity);
  570. }
  571. NodeType *__p = __node->prev;
  572. NodeType *__n = __node->next;
  573. if(__node == _M_head)
  574. {
  575. _M_head = __n;
  576. _M_head->prev = null;
  577. }
  578. else if(__node == _M_tail)
  579. {
  580. _M_tail = __p;
  581. _M_tail->next = null;
  582. }
  583. else
  584. {
  585. __p->next = __n;
  586. __n->prev = __p;
  587. }
  588. delete __node;
  589. --_M_count;
  590. }
  591. private:
  592. size_type _M_capacity;
  593. size_type _M_count;
  594. NodeType *_M_head;
  595. NodeType *_M_tail;
  596. NodeType **_M_data;
  597. };
  598. #ifdef __GNUC__
  599. #pragma GCC diagnostic pop
  600. #elif defined(Clang)
  601. #pragma clang diagnostic pop
  602. #elif defined(_MSC_VER)
  603. #pragma warning(pop)
  604. #endif
  605. #endif // HASH_TABLE_H

头文件:HashMap.h

  1. #ifndef HASH_MAP_H
  2. #define HASH_MAP_H
  3. #include "HashTable.h"
  4. template<typename _Key,
  5. typename _Value,
  6. typename _Hash = Hash<_Key>,
  7. typename _EqualTo = Equal<_Key>
  8. >
  9. class HashMap
  10. {
  11. private:
  12. typedef HashTable<_Key, std::pair<_Key, _Value>, _Hash, _EqualTo> _HashTable;
  13. public:
  14. typedef typename _HashTable::iterator iterator;
  15. typedef typename _HashTable::const_iterator const_iterator;
  16. public:
  17. typedef _Key key_type;
  18. typedef _Value mapped_type;
  19. typedef std::pair<key_type, mapped_type> value_type;
  20. typedef typename _HashTable::size_type size_type;
  21. public:
  22. HashMap() {}
  23. HashMap(const HashMap &__m)
  24. : _M_impl(__m._M_impl) { }
  25. #if __cplusplus >= 201103L
  26. HashMap(HashMap &&__m)
  27. : _M_impl(std::move(__m._M_impl)) { }
  28. #endif
  29. _Value& at(const _Key &__k)
  30. { return _M_impl.at(__k, value_type(__k, mapped_type())).second; }
  31. _Value& operator[](const _Key &__k)
  32. { return _M_impl.at(__k, value_type(__k, mapped_type())).second; }
  33. std::pair<iterator, bool> insert(const _Key &__k, const _Value &__v)
  34. { return _M_impl.insert(__k, value_type(__k, __v)); }
  35. std::pair<iterator, bool> insert(const std::pair<_Key, _Value> &__p)
  36. { return _M_impl.insert(__p.first, __p); }
  37. #if __cplusplus >= 201103L
  38. std::pair<iterator, bool> insert(std::pair<_Key, _Value> &&__p)
  39. { return _M_impl.insert(__p.first, std::move(__p)); }
  40. #endif
  41. void erase(const_iterator __i)
  42. {
  43. const_iterator __e = __i;
  44. _M_impl.erase(__i, ++__e);
  45. }
  46. void erase(iterator __i)
  47. {
  48. const_iterator __e = __i;
  49. _M_impl.erase(__i, ++__e);
  50. }
  51. void erase(const_iterator __b, const_iterator __e)
  52. { _M_impl.erase(__b, __e); }
  53. size_type erase(const _Key &__k)
  54. {
  55. iterator __f = find(__k);
  56. if(__f == end())
  57. { return 0; }
  58. _M_impl.erase(__f);
  59. return 1;
  60. }
  61. size_type max_size() const
  62. { return _M_impl.max_size(); }
  63. void rehash(size_type __s)
  64. { _M_impl.rehash(__s); }
  65. size_type size() const
  66. { return _M_impl.size(); }
  67. size_type count(const _Key &__k) const
  68. { return static_cast<size_type>(contains(__k)); }
  69. size_type bucket_count() const
  70. { return _M_impl.bucket_count(); }
  71. void swap(HashMap &__m)
  72. { _M_impl.swap(__m._M_impl); }
  73. bool empty() const
  74. { return _M_impl.empty(); }
  75. iterator find(const _Key &__k)
  76. { return _M_impl.find(__k); }
  77. const_iterator find(const _Key &__k) const
  78. { return _M_impl.find(__k); }
  79. bool contains(const _Key &__k) const
  80. { return find(__k) != end(); }
  81. iterator begin()
  82. { return _M_impl.begin(); }
  83. const_iterator begin() const
  84. { return _M_impl.begin(); }
  85. const_iterator cbegin() const
  86. { return _M_impl.cbegin(); }
  87. iterator end()
  88. { return _M_impl.end(); }
  89. const_iterator end() const
  90. { return _M_impl.end(); }
  91. const_iterator cend() const
  92. { return _M_impl.cend(); }
  93. void clear()
  94. { _M_impl.clear(); }
  95. private:
  96. _HashTable _M_impl;
  97. };
  98. #endif // HASH_MAP_H

头文件:HashSet.h

  1. #ifndef HASH_SET_H
  2. #define HASH_SET_H
  3. #include "HashTable.h"
  4. template<typename _Key,
  5. typename _Hash = Hash<_Key>,
  6. typename _EqualTo = Equal<_Key>
  7. >
  8. class HashSet
  9. {
  10. private:
  11. typedef HashTable<_Key, _Key, _Hash, _EqualTo> _HashTable;
  12. public:
  13. typedef typename _HashTable::const_iterator iterator;
  14. typedef typename _HashTable::const_iterator const_iterator;
  15. public:
  16. typedef _Key key_type;
  17. typedef _Key value_type;
  18. typedef typename _HashTable::size_type size_type;
  19. public:
  20. HashSet() {}
  21. HashSet(const HashSet &__s)
  22. : _M_impl(__s._M_impl) { }
  23. #if __cplusplus >= 201103L
  24. HashSet(HashSet &&__s)
  25. : _M_impl(std::move(__s._M_impl)) { }
  26. #endif
  27. std::pair<iterator, bool> insert(const _Key &__k)
  28. { return _M_impl.insert(__k, __k); }
  29. void erase(const_iterator __i)
  30. {
  31. const_iterator __e = __i;
  32. _M_impl.erase(__i, ++__e);
  33. }
  34. void erase(const_iterator __b, const_iterator __e)
  35. { _M_impl.erase(__b, __e); }
  36. size_type erase(const _Key &__k)
  37. {
  38. iterator __f = find(__k);
  39. if(__f == end())
  40. { return 0; }
  41. _M_impl.erase(__f);
  42. return 1;
  43. }
  44. size_type max_size() const
  45. { return _M_impl.max_size(); }
  46. void rehash(size_type __s)
  47. { _M_impl.rehash(__s); }
  48. size_type size() const
  49. { return _M_impl.size(); }
  50. size_type count(const _Key &__k) const
  51. { return static_cast<size_type>(contains(__k)); }
  52. size_type bucket_count() const
  53. { return _M_impl.bucket_count(); }
  54. void swap(HashSet &__m)
  55. { _M_impl.swap(__m._M_impl); }
  56. bool empty() const
  57. { return _M_impl.empty(); }
  58. iterator find(const _Key &__k)
  59. { return _M_impl.find(__k); }
  60. const_iterator find(const _Key &__k) const
  61. { return _M_impl.find(__k); }
  62. bool contains(const _Key &__k) const
  63. { return find(__k) != end(); }
  64. iterator begin()
  65. { return _M_impl.begin(); }
  66. const_iterator begin() const
  67. { return _M_impl.begin(); }
  68. const_iterator cbegin() const
  69. { return _M_impl.cbegin(); }
  70. iterator end()
  71. { return _M_impl.end(); }
  72. const_iterator end() const
  73. { return _M_impl.end(); }
  74. const_iterator cend() const
  75. { return _M_impl.cend(); }
  76. void clear()
  77. { _M_impl.clear(); }
  78. private:
  79. _HashTable _M_impl;
  80. };
  81. #endif // HASH_SET_H

4. 测试代码

源码:

  1. #include <iostream>
  2. #include "HashMap.h"
  3. #include "HashSet.h"
  4. struct A
  5. {
  6. int v;
  7. A(int vv = 0) : v(vv)
  8. { }
  9. friend std::ostream& operator<<(std::ostream &os, const A &a)
  10. {
  11. os << a.v;
  12. return os;
  13. }
  14. bool operator==(const A &a) const
  15. { return v == a.v; }
  16. };
  17. struct A_Hash
  18. {
  19. HashType operator()(const A &a) const
  20. { return static_cast<HashType>(a.v); }
  21. };
  22. typedef HashMap<int, A, A_Hash> TestHashMap;
  23. typedef HashSet<A, A_Hash> TestHashSet;
  24. static void print(const TestHashMap &a)
  25. {
  26. for(TestHashMap::const_iterator it = a.begin(); it != a.end(); ++it)
  27. {
  28. std::cout << it->second.v << ' ';
  29. }
  30. std::cout << std::endl;
  31. }
  32. static void print(const TestHashSet &a)
  33. {
  34. for(TestHashSet::const_iterator it = a.begin(); it != a.end(); ++it)
  35. {
  36. std::cout << *it << ' ';
  37. }
  38. std::cout << std::endl;
  39. }
  40. static void print_insert(TestHashMap &a, int k, const A &v)
  41. {
  42. static int index = 0;
  43. std::cout << "---------------insert node: " << ++index << "-------------------" << std::endl;
  44. std::cout << "node: " << k << "<--->" << v << std::endl;
  45. a.insert(std::make_pair(k, v));
  46. std::cout << "bkt size : " << a.bucket_count() << std::endl;
  47. print(a);
  48. }
  49. static void test_hashmap()
  50. {
  51. std::cout << "******************** test_hashmap ***********************" << std::endl;
  52. TestHashMap a;
  53. print_insert(a, 1, A(10));
  54. print_insert(a, 3, A(30));
  55. print_insert(a, 2, A(20));
  56. print_insert(a, 7, A(70));
  57. print_insert(a, 0, A(0));
  58. print_insert(a, 4, A(4));
  59. print_insert(a, 8, A(80));
  60. a[20] = A(200);
  61. std::cout << "------------------find node----------------" << std::endl;
  62. TestHashMap::iterator found = a.find(0);
  63. if(found != a.end())
  64. {
  65. std::cout << "0 is exists! its value: " << found->second << std::endl;
  66. }
  67. found = a.find(100);
  68. if(found == a.end())
  69. {
  70. std::cout << "100 is not exists!!" << std::endl;
  71. }
  72. std::cout << "--------------remove node: 2--20" << std::endl;
  73. a.erase(a.find(2));
  74. print(a);
  75. }
  76. static void test_hashset()
  77. {
  78. std::cout << "******************** test_hashset ***********************" << std::endl;
  79. TestHashSet a;
  80. a.insert(A(10));
  81. a.insert(A(-1));
  82. a.insert(A(1));
  83. a.insert(A(8));
  84. a.insert(A(100));
  85. std::cout << "node list: ";
  86. print(a);
  87. std::cout << "node 10 is exists? " << std::boolalpha << a.contains(10) << std::endl;
  88. std::cout << "---------- remove node : -1 -----------------" << std::endl;
  89. TestHashSet::const_iterator found = a.find(A(-1));
  90. if(found != a.end())
  91. {
  92. a.erase(found);
  93. }
  94. std::cout << "node list: ";
  95. print(a);
  96. }
  97. int main()
  98. {
  99. test_hashmap();
  100. test_hashset();
  101. return 0;
  102. }

输出结果:

5. 结尾

如有问题,欢迎指出!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/227324
推荐阅读
相关标签
  

闽ICP备14008679号