• unordered_map,unordered_set模拟实现


    目录

    一 . 底层结构--哈希

    1.直接定址法

    2. 除留余数法 + 哈希桶

    3. 一些定义 

    二 . 模拟实现哈希表

    1.哈希表框架

    ​编辑

    2.插入

     3.查找 

    4 . 删除

    5.解决使用问题

    6.完整代码

    三 .实现unordered_map, unordered_set

    1. 初步实现unordered_map, unordered_set

    2.加上迭代器(自行理解)

     3.测试用例


    一 . 底层结构--哈希

    哈希思想:构造一种存储结构,通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素。
    哈希方法构造出来的结构称为哈希表(Hash Table)(或者称散列表)

    1.直接定址法

    2. 除留余数法 + 哈希桶

    如果数据过多,并且数据很散,直接定址法不适合。

    3. 一些定义 

    不同关键字(4,14,24,84)通过相同的方法(% 10)计算出相同的哈希地址,该种现象称为哈希冲突或哈希碰撞。

    解决哈希冲突两种常见的方法是:闭散列和开散列

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

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

    (我们采用的是开散列法)

    二 . 模拟实现哈希表

    1.哈希表框架


     

    代码: 

    1. //节点
    2. template<class K, class V>
    3. struct HashNode
    4. {
    5. HashNode(const pair& kv)
    6. :_kv(kv)
    7. , _next(nullptr)
    8. {}
    9. pair _kv;
    10. HashNode* _next;
    11. };
    12. template<class K, class V>
    13. {
    14. typedef HashNode Node;
    15. public:
    16. HashTable()
    17. {
    18. _tables.resize(10, nullptr);
    19. }
    20. ~HashTable()
    21. {
    22. for (size_t i = 0; i < _tables.size(); i++)
    23. {
    24. Node* cur = _tables[i];
    25. while (cur)
    26. {
    27. Node* next = cur->_next;
    28. delete cur;
    29. cur = next;
    30. }
    31. }
    32. }
    33. //删除
    34. //插入
    35. //查找
    36. private:
    37. vector _tables;
    38. size_t _n = 0; // 哈希表实际元素个数
    39. }

    _n存在的意义:判断_tables什么时候扩容。

    开散列最好的情况是:每个哈希桶中刚好挂一个节点,再继续插入元素时,每一次都会发生哈希冲突,因此,在元素个数刚好等于桶的个数时,可以给哈希表增容。
     

    2.插入

    1. bool Insert(const pair& kv)
    2. {
    3. if(Find(kv.first))
    4. return false;
    5. //扩容
    6. if (_n / _tables.size() == 1)
    7. {
    8. size_t newSize = _tables.size() * 2;
    9. vector newTables;
    10. newTables.resize(newSize, nullptr);
    11. for (size_t i = 0; i < _tables.size(); i++)
    12. {
    13. Node* cur = _tables[i];
    14. while (cur)
    15. {
    16. size_t hashi = cur->_kv.first % newTables.size();
    17. cur->_next = newTables[hashi];
    18. newTables[hashi] = cur;
    19. }
    20. _tables[i] = nullptr;
    21. }
    22. _tables.swap(newTables);
    23. }
    24. size_t hashi = kv.first % _tables.size();
    25. Node* newnode = new Node(kv);
    26. newnode->_next = _tables[hashi];
    27. _tables[hashi] = newnode;
    28. _n++;
    29. return false;
    30. }

     3.查找 

    1. Node* Find(const K& key)
    2. {
    3. size_t hashi = key % _tables.size();//找到插入位置
    4. Node* cur = _tables[hashi];
    5. while (cur)
    6. {
    7. if (cur->_kv.first == key)
    8. {
    9. return cur;
    10. }
    11. cur = cur->_next;
    12. }
    13. return nullptr;
    14. }

    4 . 删除

     

    1. bool erase(const K& key)
    2. {
    3. size_t hashi = key % _tables.size();
    4. Node* cur = _tables[hashi];
    5. Node* prev = nullptr;
    6. if (cur->_kv.first == key)
    7. {
    8. _tables[hashi] = nullptr;
    9. return true;
    10. }
    11. while (cur)
    12. {
    13. if (cur->_kv.first == key)
    14. {
    15. prev->_next = cur->_next;
    16. delete cur;
    17. return true;
    18. }
    19. prev = cur;
    20. cur = cur->_next;
    21. }
    22. return false;
    23. }

    5.解决使用问题

    如果kv.first为string或者其他类型,就会出问题。

    解决:

    1. template<class K>
    2. struct HashFunc
    3. {
    4. size_t operator()(const K& key)
    5. {
    6. return (size_t)key;
    7. }
    8. };
    9. template<>
    10. struct HashFunc
    11. {
    12. size_t operator()(const string& key)
    13. {
    14. size_t sum = 0;
    15. for (auto& e : key)
    16. {
    17. sum *= 31;
    18. sum += e;
    19. }
    20. return sum;
    21. }
    22. };

    接着把所有用除留余数法的部分进行修改:

    6.完整代码

    1. #pragma once
    2. template<class K, class V>
    3. struct HashNode
    4. {
    5. HashNode(const pair& kv)
    6. :_kv(kv)
    7. , _next(nullptr)
    8. {}
    9. pair _kv;
    10. HashNode* _next;
    11. };
    12. template<class K>
    13. struct HashFunc
    14. {
    15. size_t operator()(const K& key)
    16. {
    17. return (size_t)key;
    18. }
    19. };
    20. template<>
    21. struct HashFunc
    22. {
    23. size_t operator()(const string& key)
    24. {
    25. size_t sum = 0;
    26. for (auto& e : key)
    27. {
    28. sum *= 31;
    29. sum += e;
    30. }
    31. return sum;
    32. }
    33. };
    34. //哈希桶
    35. template<class K, class V, class Hash = HashFunc>
    36. class HashTable
    37. {
    38. typedef HashNode Node;
    39. Hash hf;
    40. public:
    41. HashTable()
    42. {
    43. _tables.resize(10, nullptr);
    44. }
    45. ~HashTable()
    46. {
    47. for (size_t i = 0; i < _tables.size(); i++)
    48. {
    49. Node* cur = _tables[i];
    50. while (cur)
    51. {
    52. Node* next = cur->_next;
    53. delete cur;
    54. cur = next;
    55. }
    56. }
    57. }
    58. bool Insert(const pair& kv)
    59. {
    60. if(Find(kv.first))
    61. return false;
    62. //扩容
    63. if (_n / _tables.size() == 1)
    64. {
    65. size_t newSize = _tables.size() * 2;
    66. vector newTables;
    67. newTables.resize(newSize, nullptr);
    68. for (size_t i = 0; i < _tables.size(); i++)
    69. {
    70. Node* cur = _tables[i];
    71. while (cur)
    72. {
    73. size_t hashi = hf(cur->_kv.first) % newTables.size();
    74. cur->_next = newTables[hashi];
    75. newTables[hashi] = cur;
    76. }
    77. _tables[i] = nullptr;
    78. }
    79. _tables.swap(newTables);
    80. }
    81. size_t hashi = hf(kv.first) % _tables.size();
    82. Node* newnode = new Node(kv);
    83. newnode->_next = _tables[hashi];
    84. _tables[hashi] = newnode;
    85. _n++;
    86. return false;
    87. }
    88. Node* Find(const K& key)
    89. {
    90. size_t hashi = hf(key) % _tables.size();
    91. Node* cur = _tables[hashi];
    92. while (cur)
    93. {
    94. if (cur->_kv.first == key)
    95. {
    96. return cur;
    97. }
    98. cur = cur->_next;
    99. }
    100. return nullptr;
    101. }
    102. bool erase(const K& key)
    103. {
    104. size_t hashi = hf(key) % _tables.size();
    105. Node* cur = _tables[hashi];
    106. Node* prev = nullptr;
    107. if (cur->_kv.first == key)
    108. {
    109. _tables[hashi] = nullptr;
    110. return true;
    111. }
    112. while (cur)
    113. {
    114. if (cur->_kv.first == key)
    115. {
    116. prev->_next = cur->_next;
    117. delete cur;
    118. return true;
    119. }
    120. prev = cur;
    121. cur = cur->_next;
    122. }
    123. return false;
    124. }
    125. private:
    126. vector _tables;
    127. size_t _n = 0;
    128. };

    三 .实现unordered_map, unordered_set

    1. 初步实现unordered_map, unordered_set

    这部分内容类似红黑树封装map,set。

    unordered_set.h

    1. #pragma once
    2. template<class K, class Hash = HashFunc>
    3. class unordered_set
    4. {
    5. struct KeyOfT
    6. {
    7. const K& operator()(const K& key)
    8. {
    9. return key;
    10. }
    11. };
    12. public:
    13. bool insert(const K& key)
    14. {
    15. return _ht.Insert(key);
    16. }
    17. bool erase(const K& key)
    18. {
    19. return _ht.Erase(key);
    20. }
    21. HashNode* find(const K& key)
    22. {
    23. return _ht.Find(key);
    24. }
    25. private:
    26. HashTable _ht;
    27. };

    unordered_map.h

    1. #pragma once
    2. template<class K, class V, class Hash = HashFunc>
    3. class unordered_map
    4. {
    5. struct KeyOfT
    6. {
    7. const K& operator()(const pair& kv)
    8. {
    9. return kv.first;
    10. }
    11. };
    12. public:
    13. bool insert(const pair& key)
    14. {
    15. return _ht.Insert(key);
    16. }
    17. bool erase(const K& key)
    18. {
    19. return _ht.Erase(key);
    20. }
    21. HashNode>* find(const K& key)
    22. {
    23. return _ht.Find(key);
    24. }
    25. private:
    26. HashTable, KeyOfT> _ht;
    27. };

    HashTable.h

    1. #pragma once
    2. template<class T>
    3. struct HashNode
    4. {
    5. HashNode(const T& data)
    6. :_data(data)
    7. , _next(nullptr)
    8. {}
    9. T _data;
    10. HashNode* _next;
    11. };
    12. template<class K>
    13. struct HashFunc
    14. {
    15. size_t operator()(const K& key)
    16. {
    17. return (size_t)key;
    18. }
    19. };
    20. template<>
    21. struct HashFunc
    22. {
    23. size_t operator()(const string& key)
    24. {
    25. size_t sum = 0;
    26. for (auto& e : key)
    27. {
    28. sum *= 31;
    29. sum += e;
    30. }
    31. return sum;
    32. }
    33. };
    34. //哈希桶
    35. template<class K, class T, class KeyOfT>
    36. class HashTable
    37. {
    38. typedef HashNode Node;
    39. HashFunc hf;
    40. KeyOfT kot;
    41. public:
    42. HashTable()
    43. {
    44. _tables.resize(10, nullptr);
    45. }
    46. ~HashTable()
    47. {
    48. for (size_t i = 0; i < _tables.size(); i++)
    49. {
    50. Node* cur = _tables[i];
    51. while (cur)
    52. {
    53. Node* next = cur->_next;
    54. delete cur;
    55. cur = next;
    56. }
    57. }
    58. }
    59. bool Insert(const T& data)
    60. {
    61. if(Find(kot(data)))
    62. return false;
    63. //扩容
    64. if (_n / _tables.size() == 1)
    65. {
    66. size_t newSize = _tables.size() * 2;
    67. vector newTables;
    68. newTables.resize(newSize, nullptr);
    69. for (size_t i = 0; i < _tables.size(); i++)
    70. {
    71. Node* cur = _tables[i];
    72. while (cur)
    73. {
    74. size_t hashi = hf(kot(cur->_data)) % newTables.size();
    75. cur->_next = newTables[hashi];
    76. newTables[hashi] = cur;
    77. }
    78. _tables[i] = nullptr;
    79. }
    80. _tables.swap(newTables);
    81. }
    82. size_t hashi = hf(kot(data)) % _tables.size();
    83. Node* newnode = new Node(data);
    84. newnode->_next = _tables[hashi];
    85. _tables[hashi] = newnode;
    86. _n++;
    87. return false;
    88. }
    89. Node* Find(const K& key)
    90. {
    91. size_t hashi = hf(key) % _tables.size();
    92. Node* cur = _tables[hashi];
    93. while (cur)
    94. {
    95. if (kot(cur->_data) == key)
    96. {
    97. return cur;
    98. }
    99. cur = cur->_next;
    100. }
    101. return nullptr;
    102. }
    103. bool Erase(const K& key)
    104. {
    105. size_t hashi = hf(key) % _tables.size();
    106. Node* cur = _tables[hashi];
    107. Node* prev = nullptr;
    108. if (kot(cur->_data) == key)
    109. {
    110. _tables[hashi] = nullptr;
    111. return true;
    112. }
    113. while (cur)
    114. {
    115. if (kot(cur->_data) == key)
    116. {
    117. prev->_next = cur->_next;
    118. delete cur;
    119. return true;
    120. }
    121. prev = cur;
    122. cur = cur->_next;
    123. }
    124. return false;
    125. }
    126. private:
    127. vector _tables;
    128. size_t _n = 0;
    129. };

    2.加上迭代器(自行理解)

    unordered_map.h

    1. #pragma once
    2. template<class K, class V, class Hash = HashFunc>
    3. class unordered_map
    4. {
    5. struct KeyOfT
    6. {
    7. const K& operator()(const pair& kv)
    8. {
    9. return kv.first;
    10. }
    11. };
    12. public:
    13. typedef typename HashTableconst K, V>, KeyOfT, Hash>::iterator iterator;
    14. iterator begin()
    15. {
    16. return _ht.begin();
    17. }
    18. iterator end()
    19. {
    20. return _ht.end();
    21. }
    22. pairbool> insert(const pair& kv)
    23. {
    24. return _ht.Insert(kv);
    25. }
    26. V& operator[](const K& key)
    27. {
    28. pairbool> ret = _ht.Insert(make_pair(key, V()));
    29. return ret.first->second;
    30. }
    31. const V& operator[](const K& key) const
    32. {
    33. pairbool> ret = _ht.Insert(make_pair(key, V()));
    34. return ret.first->second;
    35. }
    36. iterator find(const K& key)
    37. {
    38. return _ht.Find(key);
    39. }
    40. bool erase(const K& key)
    41. {
    42. return _ht.Erase(key);
    43. }
    44. private:
    45. HashTableconst K, V>, KeyOfT, Hash> _ht;
    46. };

    unordered_set.h

    1. #pragma once
    2. template<class K, class Hash = HashFunc>
    3. class unordered_set
    4. {
    5. struct KeyOfT
    6. {
    7. const K& operator()(const K& key)
    8. {
    9. return key;
    10. }
    11. };
    12. public:
    13. typedef typename HashTable::const_iterator iterator;
    14. typedef typename HashTable::const_iterator const_iterator;
    15. const_iterator begin() const
    16. {
    17. return _ht.begin();
    18. }
    19. const_iterator end() const
    20. {
    21. return _ht.end();
    22. }
    23. pairbool> insert(const K& key)
    24. {
    25. auto ret = _ht.Insert(key);
    26. return pairbool>(const_iterator(ret.first._node, ret.first._pht, ret.first._hashi), ret.second);
    27. }
    28. iterator find(const K& key)
    29. {
    30. return _ht.Find(key);
    31. }
    32. private:
    33. HashTable _ht;
    34. };

    HashTable.h

    1. #pragma once
    2. template<class T>
    3. struct HashNode
    4. {
    5. HashNode(const T& data)
    6. :_data(data)
    7. , _next(nullptr)
    8. {}
    9. T _data;
    10. HashNode* _next;
    11. };
    12. template<class K>
    13. struct HashFunc
    14. {
    15. size_t operator()(const K& key)
    16. {
    17. return (size_t)key;
    18. }
    19. };
    20. template<>
    21. struct HashFunc
    22. {
    23. size_t operator()(const string& key)
    24. {
    25. size_t sum = 0;
    26. for (auto& e : key)
    27. {
    28. sum *= 31;
    29. sum += e;
    30. }
    31. return sum;
    32. }
    33. };
    34. //前置声明
    35. template<class K, class T, class KeyOfT, class Hash>
    36. class HashTable;
    37. //迭代器
    38. template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash = HashFunc>
    39. struct _HTIterator
    40. {
    41. typedef HashNode Node;
    42. typedef _HTIterator Self;
    43. Node* _node;
    44. size_t _hashi;
    45. const HashTable* _pht;
    46. _HTIterator(Node* node, HashTable* pht, size_t hashi)
    47. :_node(node)
    48. , _hashi(hashi)
    49. , _pht(pht)
    50. {}
    51. _HTIterator(Node* node, const HashTable* pht, size_t hashi)
    52. :_node(node)
    53. , _hashi(hashi)
    54. , _pht(pht)
    55. {}
    56. Self& operator++()
    57. {
    58. if (_node->_next)
    59. {
    60. _node = _node->_next;
    61. }
    62. else//需要哈希表
    63. {
    64. ++_hashi;
    65. while (_hashi < _pht->_tables.size())
    66. {
    67. if (_pht->_tables[_hashi])
    68. {
    69. _node = _pht->_tables[_hashi];
    70. break;
    71. }
    72. ++_hashi;
    73. }
    74. if (_hashi == _pht->_tables.size())
    75. {
    76. _node = nullptr;
    77. }
    78. }
    79. return *this;
    80. }
    81. bool operator!=(const Self& s)
    82. {
    83. return _node != s._node;
    84. }
    85. Ref operator*()
    86. {
    87. return _node->_data;
    88. }
    89. Ptr operator->()
    90. {
    91. return &(_node->_data);
    92. }
    93. };
    94. //哈希桶
    95. template<class K, class T, class KeyOfT, class Hash = HashFunc>
    96. class HashTable
    97. {
    98. public:
    99. typedef HashNode Node;
    100. //为了访问HashTable的私有成员
    101. template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash>
    102. friend struct _HTIterator;
    103. typedef _HTIterator iterator;
    104. typedef _HTIteratorconst T&, const T*, KeyOfT, Hash> const_iterator;
    105. Hash hf;
    106. KeyOfT kot;
    107. HashTable()
    108. {
    109. _tables.resize(10, nullptr);
    110. }
    111. ~HashTable()
    112. {
    113. for (size_t i = 0; i < _tables.size(); i++)
    114. {
    115. Node* cur = _tables[i];
    116. while (cur)
    117. {
    118. Node* next = cur->_next;
    119. delete cur;
    120. cur = next;
    121. }
    122. }
    123. }
    124. iterator begin()
    125. {
    126. for (size_t i = 0; i < _tables.size(); i++)
    127. {
    128. if (_tables[i])
    129. {
    130. return iterator(_tables[i], this, i);
    131. }
    132. }
    133. return end();
    134. }
    135. iterator end()
    136. {
    137. return iterator(nullptr, this, -1);
    138. }
    139. const_iterator begin() const
    140. {
    141. for (size_t i = 0; i < _tables.size(); i++)
    142. {
    143. if (_tables[i])
    144. {
    145. return const_iterator(_tables[i], this, i);
    146. }
    147. }
    148. return end();
    149. }
    150. const_iterator end() const
    151. {
    152. return const_iterator(nullptr, this, -1);
    153. }
    154. pairbool> Insert(const T& data)
    155. {
    156. iterator it = Find(kot(data));
    157. if (it != end())
    158. return make_pair(it, false);
    159. //扩容
    160. if (_n / _tables.size() == 1)
    161. {
    162. size_t newSize = _tables.size() * 2;
    163. vector newTables;
    164. newTables.resize(newSize, nullptr);
    165. for (size_t i = 0; i < _tables.size(); i++)
    166. {
    167. Node* cur = _tables[i];
    168. while (cur)
    169. {
    170. size_t hashi = hf(kot(cur->_data)) % newTables.size();
    171. cur->_next = newTables[hashi];
    172. newTables[hashi] = cur;
    173. }
    174. _tables[i] = nullptr;
    175. }
    176. _tables.swap(newTables);
    177. }
    178. size_t hashi = hf(kot(data)) % _tables.size();
    179. Node* newnode = new Node(data);
    180. newnode->_next = _tables[hashi];
    181. _tables[hashi] = newnode;
    182. _n++;
    183. return make_pair(iterator(newnode, this, hashi), true);
    184. }
    185. iterator Find(const K& key)
    186. {
    187. size_t hashi = hf(key) % _tables.size();
    188. Node* cur = _tables[hashi];
    189. while (cur)
    190. {
    191. if (kot(cur->_data) == key)
    192. {
    193. return iterator(cur, this, hashi);
    194. }
    195. cur = cur->_next;
    196. }
    197. return end();
    198. }
    199. bool Erase(const K& key)
    200. {
    201. size_t hashi = hf(key) % _tables.size();
    202. Node* cur = _tables[hashi];
    203. Node* prev = nullptr;
    204. if (kot(cur->_data) == key)
    205. {
    206. _tables[hashi] = nullptr;
    207. return true;
    208. }
    209. while (cur)
    210. {
    211. if (kot(cur->_data) == key)
    212. {
    213. prev->_next = cur->_next;
    214. delete cur;
    215. return true;
    216. }
    217. prev = cur;
    218. cur = cur->_next;
    219. }
    220. return false;
    221. }
    222. private:
    223. vector _tables;
    224. size_t _n = 0;
    225. };

     3.测试用例

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. using namespace std;
    7. #include"HashTable.h"
    8. #include"myunordered_set.h"
    9. #include"myunordered_map.h"
    10. void test()
    11. {
    12. //HashTable ht;
    13. //ht.Insert(make_pair("西瓜", 1));
    14. //HashNode* ret = ht.Find("西瓜");
    15. //ret->_kv.second++;
    16. //cout << ret->_kv.first << ":" << ret->_kv.second << endl;;
    17. //ht.Insert(make_pair("桃子", 1));
    18. //ht.Insert(make_pair("桃子", 2));
    19. //ht.Insert(make_pair("苹果", 1));
    20. }
    21. //void testset()
    22. //{
    23. // unordered_set us;
    24. // us.insert("西瓜");
    25. // us.insert("香蕉");
    26. // us.insert("苹果");
    27. // us.insert("西瓜");
    28. //
    29. // us.erase("西瓜");
    30. // HashNode* ret = us.find("香蕉");
    31. // cout << ret->_data << endl;
    32. //}
    33. //void testmap()
    34. //{
    35. // string arr[] = { "西瓜", "香蕉", "西瓜", "苹果", "西瓜", "西瓜", "香蕉", "西瓜" };
    36. // unordered_map up;
    37. // for (auto e : arr)
    38. // {
    39. // HashNode>* ret = up.find(e);
    40. // if (ret)
    41. // {
    42. // ret->_data.second++;
    43. // cout << ret->_data.first << ":" << ret->_data.second << endl;
    44. //
    45. // }
    46. // else
    47. // {
    48. // up.insert(make_pair(e, 1));
    49. // }
    50. // }
    51. //
    52. //}
    53. void test_set()
    54. {
    55. // 17:05
    56. unordered_set<int> us;
    57. us.insert(5);
    58. us.insert(15);
    59. us.insert(52);
    60. us.insert(3);
    61. unordered_set<int>::iterator it = us.begin();
    62. while (it != us.end())
    63. {
    64. cout << *it << " ";
    65. ++it;
    66. }
    67. cout << endl;
    68. for (auto e : us)
    69. {
    70. cout << e << " ";
    71. }
    72. cout << endl;
    73. }
    74. void test_map()
    75. {
    76. //unordered_map dict;
    77. //dict.insert(make_pair("sort", ""));
    78. //dict.insert(make_pair("string", "ַ"));
    79. //dict.insert(make_pair("insert", ""));
    80. //for (auto& kv : dict)
    81. //{
    82. // //kv.first += 'x';
    83. // kv.second += 'x';
    84. // cout << kv.first << ":" << kv.second << endl;
    85. //}
    86. //cout << endl;
    87. string arr[] = { "西瓜", "苹果", "苹果", "胡萝卜", "梨子", "橘子", "哈密瓜", "桃子", "西瓜", "西瓜", "梨子" };
    88. unordered_mapint> count_map;
    89. for (auto& e : arr)
    90. {
    91. count_map[e]++;
    92. }
    93. for (auto& kv : count_map)
    94. {
    95. cout << kv.first << ":" << kv.second << endl;
    96. }
    97. cout << endl;
    98. }
    99. int main()
    100. {
    101. //test();
    102. //testset();
    103. //testmap();
    104. //test_set();
    105. test_map();
    106. return 0;
    107. }

  • 相关阅读:
    强化学习从基础到进阶-案例与实践[2]:马尔科夫决策、贝尔曼方程、动态规划、策略价值迭代
    寻找更好的分类模型loss
    嵌入式学习-qt-Day4
    我们公司使用了6年的Spring Boot项目部署方案,打包 + 一键部署,稳的一批
    【斗破年番】蝎毕岩决战小医仙,魂殿铁护法出场,彩鳞再霸气护夫
    SSM框架--Spring配置文件
    敏捷.敏捷项目管理第二版.Jim Highsmith
    洛谷100题DAY6
    C/C++test——高效完成白盒测试
    React 重${}【ES6 引入了模板字符串解决这个问题】
  • 原文地址:https://blog.csdn.net/Pursue_Harmony/article/details/134485211