当前位置:   article > 正文

unordered_map和unordered_set实现(底层封装哈希表)

unordered_map和unordered_set实现(底层封装哈希表)

个人主页:Lei宝啊 

愿所有美好如期而遇


 


前言

在看这篇文章前,建议先了解哈希表的实现:哈希表模拟实现

如果说你对哈希表的实现很清楚,那么可以直接往下看,但是本篇文章对unordered_map和unordered_set的封装使用的哈希表是哈希表模拟实现的一种更改。

我们会指出哪里做了更改以及为什么做更改,但是上篇文章提起过的这里不会再提及。

这里贴出哈希表代码:

  1. //开散列哈希表
  2. namespace Open
  3. {
  4. template<class K, class V>
  5. struct HashNode
  6. {
  7. HashNode<K, V>* next;
  8. pair<K, V> _kv;
  9. HashNode(const pair<K, V>& kv)
  10. :next(nullptr)
  11. ,_kv(kv)
  12. {}
  13. };
  14. template<class K, class V, class Hash = HashFunc<K>>
  15. class HashTable;
  16. template<class K, class V, class Hash = HashFunc<K>>
  17. class HashIterator
  18. {
  19. typedef HashNode<K, V> Node;
  20. typedef HashTable<K, V, Hash> hstable;
  21. typedef HashIterator<K, V, Hash> iterator;
  22. public:
  23. HashIterator(Node* n, hstable* h)
  24. :node(n)
  25. ,hst(h)
  26. {}
  27. iterator& operator++()
  28. {
  29. if (node->next)
  30. {
  31. node = node->next;
  32. }
  33. else
  34. {
  35. Hash hs;
  36. int pos = hs(node->_kv.first) % hst->_table.size();
  37. pos++;
  38. while (pos < hst->_table.size())
  39. {
  40. if (hst->_table[pos])
  41. {
  42. node = hst->_table[pos];
  43. break;
  44. }
  45. pos++;
  46. }
  47. if (pos == hst->_table.size())
  48. node = nullptr;
  49. }
  50. return *this;
  51. }
  52. pair<K, V>& operator*()
  53. {
  54. return node->_kv;
  55. }
  56. bool operator!=(const iterator& s)
  57. {
  58. return node != s.node;
  59. }
  60. private:
  61. Node* node;
  62. hstable* hst;
  63. };
  64. template<class K, class V, class Hash>
  65. class HashTable
  66. {
  67. template<class K, class V, class Hash>
  68. friend class HashIterator;
  69. public:
  70. typedef HashIterator<K, V, Hash> iterator;
  71. typedef HashNode<K, V> Node;
  72. iterator begin()
  73. {
  74. for (auto& e : _table)
  75. {
  76. if (e)
  77. {
  78. return iterator(e, this);
  79. }
  80. }
  81. return end();
  82. }
  83. iterator end()
  84. {
  85. return iterator(nullptr, this);
  86. }
  87. HashTable()
  88. {
  89. _table.resize(10);
  90. }
  91. Node* Find(const K& key)
  92. {
  93. Hash hs;
  94. int pos = hs(key) % _table.size();
  95. Node* cur = _table[pos];
  96. while (cur)
  97. {
  98. if (cur->_kv.first == key)
  99. return cur;
  100. cur = cur->next;
  101. }
  102. return nullptr;
  103. }
  104. ~HashTable()
  105. {
  106. for (auto& e : _table)
  107. {
  108. Node* cur = e;
  109. while (cur)
  110. {
  111. Node* next = cur->next;
  112. delete cur;
  113. cur = next;
  114. }
  115. e = nullptr;
  116. }
  117. }
  118. bool insert(const pair<K, V>& kv)
  119. {
  120. if (Find(kv.first))
  121. return false;
  122. Hash hs;
  123. if (_table.size() == _size)
  124. {
  125. vector<Node*> newtable;
  126. newtable.resize(_table.size() * 2);
  127. for (auto e : _table)
  128. {
  129. Node* cur = e;
  130. Node* next;
  131. while (cur)
  132. {
  133. int pos = hs(cur->_kv.first) % newtable.size();
  134. next = cur->next;
  135. cur->next = newtable[pos];
  136. newtable[pos] = cur;
  137. cur = next;
  138. }
  139. }
  140. _table.swap(newtable);
  141. }
  142. int pos = hs(kv.first) % _table.size();
  143. Node* cur = _table[pos];
  144. Node* newnode = new Node(kv);
  145. newnode->next = _table[pos];
  146. _table[pos] = newnode;
  147. _size++;
  148. return true;
  149. }
  150. bool Erase(const K& key)
  151. {
  152. Hash hs;
  153. int pos = hs(key) % _table.size();
  154. Node* prev = nullptr;
  155. Node* cur = _table[pos];
  156. while (cur)
  157. {
  158. if (cur->_kv.first == key)
  159. {
  160. if (prev)
  161. {
  162. prev->next = cur->next;
  163. }
  164. else
  165. {
  166. _table[pos] = nullptr;
  167. }
  168. delete cur;
  169. --_size;
  170. return true;
  171. }
  172. prev = cur;
  173. cur = cur->next;
  174. }
  175. return false;
  176. }
  177. private:
  178. vector<Node*> _table;
  179. size_t _size = 0;
  180. };
  181. }

为封装而基于哈希表做的更改

首先是模板参数,我们改为T,因为将来这个哈希表我们不仅仅unordered_map要封装,unordered_set也要使用,所以T可以是key,也可以是pair<K,V>

  1. template<class T>
  2. struct HashNode
  3. {
  4. HashNode<T>* next;
  5. T _data;
  6. HashNode(const T& data)
  7. :next(nullptr)
  8. ,_data(data)
  9. {}
  10. };

再一个就是HashTable和HashIterator模板参数的更改,多出了KeyOfT这个仿函数,这个是为了提取节点的key值,因为我们不知道节点是pair还是key,所以需要这样一个仿函数。

	template<class K, class T, class KeyOfT, class Hash>

再一个修改就是Find和insert的返回值,我们改为了pair<iterator,bool>

iterator Find(const K& key)
pair<iterator,bool> insert(const T& data)

 其他没有什么大的修改,都是基于上面修改连锁带来的修改,我们下面贴出修改后的代码。

  1. //开散列哈希表
  2. namespace Open
  3. {
  4. template<class T>
  5. struct HashNode
  6. {
  7. HashNode<T>* next;
  8. T _data;
  9. HashNode(const T& data)
  10. :next(nullptr)
  11. ,_data(data)
  12. {}
  13. };
  14. template<class K, class T, class KeyOfT, class Hash>
  15. class HashTable;
  16. template<class K, class T, class KeyOfT, class Hash>
  17. class HashIterator
  18. {
  19. typedef HashNode<T> Node;
  20. typedef HashTable<K, T, KeyOfT, Hash> hstable;
  21. typedef HashIterator<K, T, KeyOfT, Hash> iterator;
  22. public:
  23. HashIterator(Node* n, hstable* h)
  24. :node(n)
  25. , hst(h)
  26. {}
  27. iterator& operator++()
  28. {
  29. if (node->next)
  30. {
  31. node = node->next;
  32. }
  33. else
  34. {
  35. KeyOfT kot;
  36. Hash hs;
  37. int pos = hs(kot(node->_data)) % hst->_table.size();
  38. pos++;
  39. while (pos < hst->_table.size())
  40. {
  41. if (hst->_table[pos])
  42. {
  43. node = hst->_table[pos];
  44. break;
  45. }
  46. pos++;
  47. }
  48. if (pos == hst->_table.size())
  49. node = nullptr;
  50. }
  51. return *this;
  52. }
  53. T& operator*()
  54. {
  55. return node->_data;
  56. }
  57. bool operator!=(const iterator& s)
  58. {
  59. return node != s.node;
  60. }
  61. private:
  62. Node* node;
  63. hstable* hst;
  64. };
  65. template<class K, class T, class KeyOfT, class Hash>
  66. class HashTable
  67. {
  68. template<class K, class T, class KeyOfT, class Hash>
  69. friend class HashIterator;
  70. public:
  71. typedef HashIterator<K, T, KeyOfT, Hash> iterator;
  72. typedef HashNode<T> Node;
  73. iterator begin()
  74. {
  75. for (auto& e : _table)
  76. {
  77. if (e)
  78. {
  79. return iterator(e, this);
  80. }
  81. }
  82. return end();
  83. }
  84. iterator end()
  85. {
  86. return iterator(nullptr, this);
  87. }
  88. HashTable()
  89. {
  90. _table.resize(10);
  91. }
  92. iterator Find(const K& key)
  93. {
  94. KeyOfT kot;
  95. Hash hs;
  96. int pos = hs(key) % _table.size();
  97. Node* cur = _table[pos];
  98. while (cur)
  99. {
  100. if (kot(cur->_data) == key)
  101. return iterator(cur, this);
  102. cur = cur->next;
  103. }
  104. return iterator(nullptr, this);
  105. }
  106. ~HashTable()
  107. {
  108. for (auto& e : _table)
  109. {
  110. Node* cur = e;
  111. while (cur)
  112. {
  113. Node* next = cur->next;
  114. delete cur;
  115. cur = next;
  116. }
  117. e = nullptr;
  118. }
  119. }
  120. pair<iterator,bool> insert(const T& data)
  121. {
  122. KeyOfT kot;
  123. iterator it = Find(kot(data));
  124. if (it != end())
  125. return make_pair(it, false);
  126. Hash hs;
  127. if (_table.size() == _size)
  128. {
  129. vector<Node*> newtable;
  130. newtable.resize(_table.size() * 2);
  131. for (auto e : _table)
  132. {
  133. Node* cur = e;
  134. Node* next;
  135. while (cur)
  136. {
  137. int pos = hs(kot(cur->_data)) % newtable.size();
  138. next = cur->next;
  139. cur->next = newtable[pos];
  140. newtable[pos] = cur;
  141. cur = next;
  142. }
  143. }
  144. _table.swap(newtable);
  145. }
  146. int pos = hs(kot(data)) % _table.size();
  147. Node* cur = _table[pos];
  148. Node* newnode = new Node(data);
  149. newnode->next = _table[pos];
  150. _table[pos] = newnode;
  151. _size++;
  152. return make_pair(iterator(newnode, this), true);
  153. }
  154. bool Erase(const K& key)
  155. {
  156. KeyOfT kot;
  157. Hash hs;
  158. int pos = hs(kot(key)) % _table.size();
  159. Node* prev = nullptr;
  160. Node* cur = _table[pos];
  161. while (cur)
  162. {
  163. if (kot(cur->_data) == key)
  164. {
  165. if (prev)
  166. {
  167. prev->next = cur->next;
  168. }
  169. else
  170. {
  171. _table[pos] = nullptr;
  172. }
  173. delete cur;
  174. --_size;
  175. return true;
  176. }
  177. prev = cur;
  178. cur = cur->next;
  179. }
  180. return false;
  181. }
  182. private:
  183. vector<Node*> _table;
  184. size_t _size = 0;
  185. };
  186. }

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/941256?site
推荐阅读
相关标签
  

闽ICP备14008679号