当前位置:   article > 正文

unordered_map unordered_set函数实现_unorderedmap的插入

unorderedmap的插入

一.unordered_map特点

1. unordered_map是存储pair<key, value>,通过key查找value
2.unordered_map对数据的存储没有特定的排序顺序。
3. unordered_map搜索比map快,但它遍历效率比较慢。
4. 它的迭代器至少是前向迭代器,不支持反向迭代器。

二.unordered_set特点

1.存储数据没有顺序

2.查找效率高,遍历效率低

3.没有重复值

4.插入效率高

5.不支持修改操作,可以先删除再插入

三.哈希

插入规则:对插入的值进行size()大小的取模,eg.14%10=4 头插到下标为4的节点处。

当size()大小==插入节点的个数 就进行扩容

结构:

哈希桶结构:有一个size()大小的顺序表,表中节点存储的是插入节点的指针Node*。

Node结构体能存储数据值,还可以保存下个节点的指针。

结构

  1. template<class T>
  2. struct HashNode
  3. {
  4. T _data;
  5. HashNode<T>* _next;
  6. HashNode(const T& data)
  7. :_data(data)
  8. , _next(nullptr)
  9. {}
  10. };
  11. template<class K, class T, class KeyOfT, class Hash = HashFunc<K>>
  12. class HashTable
  13. {
  14. template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash >
  15. friend struct HashIterator;
  16. typedef HashNode<T> Node;
  17. private:
  18. vector<Node*> _tables;
  19. size_t _n;
  20. };

_tables顺序表 _n记录插入的个数 Node插入节点结构 T存储数据类型

KeyOfT用于从T类型中取出key值 Hash将key值转换为一一对应的int值

构造 析构函数

这里定义的Node结构,它没有自己的析构函数,我们要手动释放空间。

vector<list<T>> vector list都有自己的析构,自动调用就可以。

  1. HashTable()
  2. {
  3. _tables.resize(10, nullptr);
  4. }
  5. ~HashTable()
  6. {
  7. for (size_t i = 0; i < _tables.size(); i++)
  8. {
  9. Node* cur = _tables[i];
  10. while (cur)
  11. {
  12. Node* next = cur->_next;
  13. delete cur;
  14. cur = next;
  15. }
  16. _tables[i] = nullptr;
  17. }
  18. }

插入

1.利用find()进行去重。

2.负载因子==1就需要进行扩容。

3.KeyOfTf取出key,再用Hash转换对应int再取模找到映射位置,进行头插。

  1. pair<Iterator, bool> Insert(const T&data)
  2. {
  3. Hash hs;
  4. KeyOfT kof;
  5. //去重
  6. Iterator it = Find(kof(data));
  7. if (it != End())
  8. {
  9. return make_pair(it,false);
  10. }
  11. //扩容
  12. if (_n == _tables.size())
  13. {
  14. vector<Node*> newtable(_tables.size() * 2, nullptr);
  15. //将原哈希表存在的值重新定位插入
  16. for (size_t i = 0; i < _tables.size(); i++)
  17. {
  18. Node* cur = _tables[i];
  19. size_t newi = hs(kof(data)) % newtable.size();
  20. while (cur)
  21. {
  22. Node* next = cur->_next;
  23. cur->_next = newtable[newi];
  24. newtable[newi] = cur;
  25. cur = next;
  26. }
  27. _tables[i] = nullptr;
  28. }
  29. //交换哈希表的vector 新建哈希表出了作用域自动销毁
  30. _tables.swap(newtable);
  31. }
  32. size_t Hashi = hs(Hash(data)) % _tables.size();
  33. //头插
  34. KeyOfT kof;
  35. Node* cur = new Node(kof(data));
  36. cur->_next = _tables[Hashi];
  37. _tables[Hashi] = cur;
  38. _n++;
  39. return make_pair(Iterator(cur,this), true);
  40. }

查找

查找值,先找到它映射的位置,再对整个桶进行遍历。找到返回对应位置,反之返回空。

  1. Iterator* Find(const K& key)
  2. {
  3. KeyOfT kof;
  4. Hash sh;
  5. size_t Hashi = hs(key) % _tables.size();
  6. Node* cur = _tables[Hashi];
  7. while (cur)
  8. {
  9. if (kof(cur->_data) == key)
  10. return Iterator(cur,this);
  11. else cur = cur->_next;
  12. }
  13. return Iterator(nullptr, this);
  14. }

删除

先通过映射找到对应桶的位置,再遍历找。

1.被删除节点是头节点,没有上一个节点。删除节点后,顺序表中存入它的下一个节点的指针。

2.不是头节点,有上一个节点。让它的prev 指向 next 再删除。

记得--_n

没找到返回fasle

  1. bool Erase(const K& key)
  2. {
  3. Hash hs;
  4. size_t Hashi = hs(key) % _tables.size();
  5. Node* prev = nullptr;
  6. Node* cur = _tables[Hashi];
  7. Node* next = cur->_next;
  8. while (cur)
  9. {
  10. KeyOfT kof;
  11. if (kof(cur->_data) == key)
  12. {
  13. //头节点就是要删除节点
  14. if (cur == _tables[Hashi])
  15. _tables[Hashi] = next;
  16. else
  17. prev->_next = next;
  18. delete cur;
  19. _n--;
  20. return true;
  21. }
  22. //找该桶的下一个节点
  23. prev = cur;
  24. cur = next;
  25. next = cur->_next;
  26. }
  27. return false;
  28. }

迭代器实现

顺序表中每个桶之间是不连续的。迭代器中只有指向Node的指针,遍历完一个桶后,就找不到下一个桶的位置了。

因此还需要顺序表,通过顺序表找到下一个桶的位置。

因为要访问HashNode HashTable结构,但它们的实现在HashIterator的后面,况且HashTable实现也需要迭代器。因此需要前置声明让编译器知道有HashNode HashTable。

  1. //前置声明
  2. template<class T>
  3. struct HashNode;
  4. template<class K, class T, class KeyOfT, class Hash >
  5. class HashTable;
  6. //迭代器
  7. template<class K, class T, class Ref,class Ptr,class KeyOfT, class Hash = HashFunc<K>>
  8. struct HashIterator
  9. {
  10. typedef HashNode<T> Node;
  11. typedef HashIterator< K, T, Ref,Ptr, KeyOfT, Hash > Self;
  12. Node* _node;
  13. HashTable< K, T, KeyOfT, Hash >* _pht;
  14. HashIterator(Node*node, HashTable< K, T, KeyOfT, Hash >*pht)
  15. :_node(node)
  16. ,_pht(pht)
  17. {}
  18. Self& operator++()
  19. {
  20. //该桶还没遍历完
  21. if (_node->_next)
  22. {
  23. _node = _node->_next;
  24. }
  25. //遍历完找下一个桶
  26. else
  27. {
  28. KeyOfT kot;
  29. Hash sh;
  30. size_t hashi = sh(kot(_node->data)) % _pht->_tables.size();
  31. hashi++;
  32. while (hashi < _pht->_tables.size())
  33. {
  34. //有桶 遍历桶
  35. if (_pht->_tables[hashi])
  36. {
  37. _node = _pht->_tables[hashi];
  38. break;
  39. }
  40. //没有++找下一个位置
  41. else
  42. hashi++;
  43. }
  44. //整个顺序表遍历结束 返回end()
  45. if (hashi == _pht->_table.size())
  46. _node = nullptr;//end()
  47. }
  48. return *this;
  49. }
  50. Ref operator*()
  51. {
  52. return _node->_data;
  53. }
  54. Ptr operator->()
  55. {
  56. return &_node->_data;
  57. }
  58. bool operator!=(const Self& s)
  59. {
  60. return _node != s._node;
  61. }
  62. };

四.unordered_set封装

因为set的key值不能修改所以传const K

  1. #include"HashTables.h"
  2. namespace wws
  3. {
  4. template<class K, class Hash = HashFunc<K>>
  5. class unordered_set
  6. {
  7. struct SetKeyOfT
  8. {
  9. const K& operator()(const K& key)
  10. {
  11. return key;
  12. }
  13. };
  14. public:
  15. typedef typename HashTable<K, const K, SetKeyOfT, Hash>::Iterator iterator;
  16. typedef typename HashTable<K, const K, SetKeyOfT, Hash>::ConstIterator const_iterator;
  17. iterator begin()
  18. {
  19. return _ht.Begin();
  20. }
  21. iterator end()
  22. {
  23. return _ht.End();
  24. }
  25. const_iterator begin() const
  26. {
  27. return _ht.Begin();
  28. }
  29. const_iterator end() const
  30. {
  31. return _ht.End();
  32. }
  33. pair<iterator, bool> insert(const K& key)
  34. {
  35. return _ht.Insert(key);
  36. }
  37. iterator Find(const K& key)
  38. {
  39. return _ht.Find(key);
  40. }
  41. bool Erase(const K& key)
  42. {
  43. return _ht.Erase(key);
  44. }
  45. private:
  46. HashTable<K, K, SetKeyOfT, Hash> _ht;
  47. };
  48. }

五.unordered_map封装

map key不能修改 但value可以修改 所以传pair<const K,V>

  1. #include"HashTables.h"
  2. namespace wws
  3. {
  4. template<class K, class V, class Hash = HashFunc<K>>
  5. class unordered_map
  6. {
  7. struct MapKeyOfT
  8. {
  9. const K& operator()(const pair<K, V>& kv)
  10. {
  11. return kv.first;
  12. }
  13. };
  14. public:
  15. typedef typename HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::Iterator iterator;
  16. typedef typename HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::ConstIterator const_iterator;
  17. iterator begin()
  18. {
  19. return _ht.Begin();
  20. }
  21. iterator end()
  22. {
  23. return _ht.End();
  24. }
  25. const_iterator begin() const
  26. {
  27. return _ht.Begin();
  28. }
  29. const_iterator end() const
  30. {
  31. return _ht.End();
  32. }
  33. pair<iterator, bool> insert(const pair<K, V>& kv)
  34. {
  35. return _ht.Insert(kv);
  36. }
  37. V& operator[](const K& key)
  38. {
  39. pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));
  40. return ret.first->second;
  41. }
  42. iterator Find(const K& key)
  43. {
  44. return _ht.Find(key);
  45. }
  46. bool Erase(const K& key)
  47. {
  48. return _ht.Erase(key);
  49. }
  50. private:
  51. HashTable<K, pair<K, V>, MapKeyOfT, Hash> _ht;
  52. };
  53. }

哈希表

  1. #include"string"
  2. #include"vector"
  3. #include<iostream>
  4. using namespace std;
  5. template<class K>
  6. struct HashFunc
  7. {
  8. size_t operator()(const K& key)
  9. {
  10. return (size_t)key;
  11. }
  12. };
  13. // 特化
  14. template<>
  15. struct HashFunc<string>
  16. {
  17. size_t operator()(const string& key)
  18. {
  19. size_t hash = 0;
  20. for (auto e : key)
  21. {
  22. hash *= 31;
  23. hash += e;
  24. }
  25. return hash;
  26. }
  27. };
  28. //前置声明
  29. template<class T>
  30. struct HashNode;
  31. template<class K, class T, class KeyOfT, class Hash >
  32. class HashTable;
  33. //迭代器
  34. template<class K, class T, class Ref,class Ptr,class KeyOfT, class Hash = HashFunc<K>>
  35. struct HashIterator
  36. {
  37. typedef HashNode<T> Node;
  38. typedef HashIterator< K, T, Ref,Ptr, KeyOfT, Hash > Self;
  39. Node* _node;
  40. HashTable< K, T, KeyOfT, Hash >* _pht;
  41. HashIterator(Node*node, HashTable< K, T, KeyOfT, Hash >*pht)
  42. :_node(node)
  43. ,_pht(pht)
  44. {}
  45. Self& operator++()
  46. {
  47. //该桶还没遍历完
  48. if (_node->_next)
  49. {
  50. _node = _node->_next;
  51. }
  52. //遍历完找下一个桶
  53. else
  54. {
  55. KeyOfT kot;
  56. Hash sh;
  57. size_t hashi = sh(kot(_node->data)) % _pht->_tables.size();
  58. hashi++;
  59. while (hashi < _pht->_tables.size())
  60. {
  61. //有桶 遍历桶
  62. if (_pht->_tables[hashi])
  63. {
  64. _node = _pht->_tables[hashi];
  65. break;
  66. }
  67. //没有++找下一个位置
  68. else
  69. hashi++;
  70. }
  71. //整个顺序表遍历结束 返回end()
  72. if (hashi == _pht->_table.size())
  73. _node = nullptr;//end()
  74. }
  75. return *this;
  76. }
  77. Ref operator*()
  78. {
  79. return _node->_data;
  80. }
  81. Ptr operator->()
  82. {
  83. return &_node->_data;
  84. }
  85. bool operator!=(const Self& s)
  86. {
  87. return _node != s._node;
  88. }
  89. };
  90. template<class T>
  91. struct HashNode
  92. {
  93. T _data;
  94. HashNode<T>* _next;
  95. HashNode(const T& data)
  96. :_data(data)
  97. , _next(nullptr)
  98. {}
  99. };
  100. template<class K, class T,class KeyOfT, class Hash = HashFunc<K>>
  101. class HashTable
  102. {
  103. template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash >
  104. friend struct HashIterator;
  105. typedef HashNode<T> Node;
  106. public:
  107. typedef HashIterator< K, T, T&, T* , KeyOfT, Hash > Iterator;
  108. typedef HashIterator< K, T, const T&,const T*, KeyOfT, Hash > ConstIterator;
  109. Iterator Begin()
  110. {
  111. for (size_t i = 0; i < _tables.size(); i++)
  112. {
  113. if (_tables[i])
  114. return Iterator(_tables[i], this);
  115. }
  116. return Iterator(nullptr, this);
  117. }
  118. Iterator End()
  119. {
  120. return Iterator(nullptr, this);
  121. }
  122. ConstIterator Begin() const
  123. {
  124. for (size_t i = 0; i < _tables.size(); i++)
  125. {
  126. if (_tables[i])
  127. return Iterator(_tables[i], this);
  128. }
  129. return Iterator(nullptr, this);
  130. }
  131. ConstIterator End() const
  132. {
  133. return Iterator(nullptr, this);
  134. }
  135. HashTable()
  136. {
  137. _tables.resize(10, nullptr);
  138. }
  139. ~HashTable()
  140. {
  141. for (size_t i = 0; i < _tables.size(); i++)
  142. {
  143. Node* cur = _tables[i];
  144. while (cur)
  145. {
  146. Node* next = cur->_next;
  147. delete cur;
  148. cur = next;
  149. }
  150. _tables[i] = nullptr;
  151. }
  152. }
  153. pair<Iterator, bool> Insert(const T&data)
  154. {
  155. Hash hs;
  156. KeyOfT kof;
  157. Iterator it = Find(kof(data));
  158. if (it != End())
  159. {
  160. return make_pair(it,false);
  161. }
  162. //扩容
  163. if (_n == _tables.size())
  164. {
  165. vector<Node*> newtable(_tables.size() * 2, nullptr);
  166. //将原哈希表存在的值重新定位插入
  167. for (size_t i = 0; i < _tables.size(); i++)
  168. {
  169. Node* cur = _tables[i];
  170. size_t newi = hs(kof(data)) % newtable.size();
  171. while (cur)
  172. {
  173. Node* next = cur->_next;
  174. cur->_next = newtable[newi];
  175. newtable[newi] = cur;
  176. cur = next;
  177. }
  178. _tables[i] = nullptr;
  179. }
  180. //交换哈希表的vector 新建哈希表出了作用域自动销毁
  181. _tables.swap(newtable);
  182. }
  183. size_t Hashi = hs(Hash(data)) % _tables.size();
  184. //头插
  185. KeyOfT kof;
  186. Node* cur = new Node(kof(data));
  187. cur->_next = _tables[Hashi];
  188. _tables[Hashi] = cur;
  189. _n++;
  190. return make_pair(Iterator(cur,this), true);
  191. }
  192. Iterator* Find(const K& key)
  193. {
  194. KeyOfT kof;
  195. Hash sh;
  196. size_t Hashi = hs(key) % _tables.size();
  197. Node* cur = _tables[Hashi];
  198. while (cur)
  199. {
  200. if (kof(cur->_data) == key)
  201. return Iterator(cur,this);
  202. else cur = cur->_next;
  203. }
  204. return Iterator(nullptr, this);
  205. }
  206. bool Erase(const K& key)
  207. {
  208. Hash hs;
  209. size_t Hashi = hs(key) % _tables.size();
  210. Node* prev = nullptr;
  211. Node* cur = _tables[Hashi];
  212. Node* next = cur->_next;
  213. while (cur)
  214. {
  215. KeyOfT kof;
  216. if (kof(cur->_data) == key)
  217. {
  218. //头节点就是要删除节点
  219. if (cur == _tables[Hashi])
  220. _tables[Hashi] = next;
  221. else
  222. prev->_next = next;
  223. delete cur;
  224. _n--;
  225. return true;
  226. }
  227. //找该桶的下一个节点
  228. prev = cur;
  229. cur = next;
  230. next = cur->_next;
  231. }
  232. return false;
  233. }
  234. private:
  235. vector<Node*> _tables;
  236. size_t _n;
  237. };

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

闽ICP备14008679号