当前位置:   article > 正文

hashmap的C++实现_用c++简单实现map集合

用c++简单实现map集合

按照hashmap的基本原理用C++实现了简单的基本功能,复杂的实现参考C++库的源码,C++最新的标准库里已经有以下四种基于hashtable的容器:

unordered_set (C++11) unordered_multiset (C++11) unordered_map (C++11) unordered_multimap (C++11)。

  1. /*
  2. * HashMap.h
  3. * Author: luxiaoxun
  4. */
  5. #ifndef HASHMAP_H_
  6. #define HASHMAP_H_
  7. #include <iostream>
  8. using namespace std;
  9. //List all the integer number no less than 57 total number is 28
  10. //And each number is about half of its next number
  11. static int prime[28] =
  12. {
  13. 57, 97, 193, 389, 769,
  14. 1543, 3079, 6151, 12289, 24593,
  15. 49157, 98317, 196613, 393241, 786433,
  16. 1572869, 3145739, 6291469, 12582917, 25165843,
  17. 50331653, 100663319, 201326611, 402653189, 805306457,
  18. 1610612741
  19. };
  20. class HashMapUtil
  21. {
  22. public:
  23. static int find_NextPrimeNumber(int current)
  24. {
  25. //Find the next prime number by searching in the prime number list
  26. int i = 0;
  27. for( ; i < 28 ; i++ )
  28. if(current < prime[i])
  29. break;
  30. return prime[i]; //return the next larger prime.
  31. }
  32. };
  33. template <class Key, class Value, class HashFunc, class EqualKey>
  34. class HashMap
  35. {
  36. private:
  37. template <class _Key, class _Value>
  38. class KeyNode
  39. {
  40. public:
  41. _Value value; //Store the value
  42. _Key key; //Store the keyword
  43. int used;
  44. //if the type of Value/Key is your own class, make sure they can handle copy constructor and operator =
  45. KeyNode():used(0){}
  46. KeyNode(const KeyNode & kn)
  47. {
  48. value = kn.value;
  49. key = kn.key;
  50. used = kn.used;
  51. }
  52. KeyNode & operator=(const KeyNode & kn)
  53. {
  54. if(this == &kn) return *this;
  55. value = kn.value;
  56. key = kn.key;
  57. used = kn.used;
  58. return *this;
  59. }
  60. };
  61. public:
  62. HashMap();
  63. ~HashMap();
  64. bool insert(const Key& hashKey, const Value& value);
  65. bool remove(const Key& hashKey);
  66. void rehash(); //use it when rehashing
  67. Value& find(const Key& hashKey);
  68. const Value& operator [](const Key& hashKey) const;
  69. Value& operator [](const Key& hashKey);
  70. private:
  71. HashFunc hash;
  72. EqualKey equal;
  73. HashMapUtil hml;
  74. KeyNode<Key ,Value> *table;
  75. int size; //current number of itmes
  76. int capacity; //capacity of the array
  77. static const double loadingFactor;
  78. int findKey(const Key& hashKey); //find the index of a key
  79. };
  80. template<class Key , class Value , class HashFunc , class EqualKey>
  81. const double HashMap<Key, Value, HashFunc, EqualKey>::loadingFactor = 0.9;
  82. template<class Key , class Value , class HashFunc , class EqualKey>
  83. HashMap<Key, Value, HashFunc, EqualKey>::HashMap()
  84. {
  85. hash = HashFunc();
  86. equal = EqualKey();
  87. hml = HashMapUtil();
  88. capacity = hml.find_NextPrimeNumber(0); //initialize the capacity with first primer 57
  89. //resize the table with capacity because an extra one is used
  90. //to return the NULL type of Value in the function find
  91. table = new KeyNode<Key,Value>[capacity+1];
  92. for(int i = 0 ; i < capacity ; i++) //initialize the table
  93. table[i].used = 0;
  94. size = 0;
  95. }
  96. template<class Key, class Value, class HashFunc, class EqualKey>
  97. HashMap<Key, Value, HashFunc, EqualKey>::~HashMap()
  98. {
  99. delete []table;
  100. }
  101. template<class Key, class Value, class HashFunc, class EqualKey>
  102. bool HashMap<Key, Value, HashFunc, EqualKey>::insert(const Key& hashKey, const Value& value)
  103. {
  104. int index = hash(hashKey)%capacity;
  105. //cout<<"Index is "<<index<<endl;
  106. if(table[index].used == 1) //the key-value's hash is unique
  107. {
  108. //cout<<"The key-value must be unique!"<<endl;
  109. return false;
  110. }
  111. table[index].used = 1; //modify the KeyNode
  112. table[index].key = hashKey;
  113. table[index].value = value;
  114. size++;
  115. //if the table's size is too large ,then rehash it
  116. if (size >= capacity * loadingFactor)
  117. rehash();
  118. return true;
  119. }
  120. template<class Key, class Value, class HashFunc, class EqualKey>
  121. void HashMap<Key, Value, HashFunc, EqualKey>::rehash()
  122. {
  123. int pastsize = capacity;
  124. //create a new array to copy the information in the old table
  125. capacity = hml.find_NextPrimeNumber(capacity);
  126. KeyNode<Key,Value>* tmp = new KeyNode<Key,Value>[capacity];
  127. for(int i = 0 ; i < pastsize ; i++)
  128. {
  129. if(table[i].used == 1) //copy the KeyNode into the tmp array
  130. {
  131. tmp[i] = table[i];
  132. }
  133. }
  134. delete []table; //release the memory of the old table
  135. table = new KeyNode<Key,Value>[capacity+1]; //resize the table
  136. for(int i = 0 ; i < capacity ; i++) //initialize the table
  137. {
  138. table[i].used = 0;
  139. }
  140. for(int i = 0 ; i < pastsize ; i++) //insert the item into the table one by one
  141. {
  142. if(tmp[i].used == 1)
  143. insert(tmp[i].key, tmp[i].value);
  144. }
  145. delete []tmp; //delete the tmp array
  146. }
  147. template<class Key, class Value, class HashFunc, class EqualKey>
  148. bool HashMap<Key, Value, HashFunc, EqualKey>::remove(const Key& hashKey)
  149. {
  150. int index = findKey(hashKey); //find the index of the key
  151. if(index < 0) //if find modify the flag with 0,else print out "no such key!"
  152. {
  153. cout<<"No such Key!"<<endl;
  154. return false;
  155. }
  156. else
  157. {
  158. table[index].used = 0;
  159. size--;
  160. return true;
  161. }
  162. }
  163. template<class Key, class Value, class HashFunc, class EqualKey>
  164. Value& HashMap<Key, Value, HashFunc, EqualKey>::find(const Key& hashKey)
  165. {
  166. int index = findKey(hashKey);
  167. if(index < 0) //if index <0 ,not found,else return the index
  168. {
  169. cout<<"can not find the key!"<<endl;
  170. return table[capacity].value; //return NULL
  171. }
  172. else
  173. {
  174. return table[index].value;
  175. }
  176. }
  177. template<class Key, class Value, class HashFunc, class EqualKey>
  178. const Value& HashMap<Key, Value, HashFunc, EqualKey>::operator[](const Key& hashKey) const
  179. {
  180. return find(hashKey); //overload the operation to return the value of the element
  181. }
  182. template<class Key, class Value, class HashFunc, class EqualKey>
  183. Value& HashMap<Key, Value, HashFunc, EqualKey>::operator[](const Key& hashKey)
  184. {
  185. return find(hashKey); //overload the operation to return the value of the element
  186. }
  187. template<class Key, class Value, class HashFunc, class EqualKey>
  188. int HashMap<Key, Value, HashFunc, EqualKey>::findKey(const Key& hashKey)
  189. {
  190. int index = hash(hashKey)%capacity;
  191. if ((table[index].used != 1) || !equal(table[index].key,hashKey))
  192. return -1;
  193. else
  194. return index;
  195. }
  196. #endif /* HASHMAP_H_ */

这里实现的key必须是unique的,否则就要处理冲突的问题,可以通过[]操作修改对应的value,但是不能通过[]添加value,标准库里的是可以的。

C++编译器不支持模板头文件和实现代码分离的编译,如果的类实现和类声明分别放在cpp文件和h头文件里,那么在测试代码里include要加上实现的代码,比如加上#include"HashMap.cpp"。使用hashmap,需要自己提供针对key的hash函数对象和equal函数对象,测试代码:

  1. #include "HashMap.h"
  2. #include <string>
  3. #include <iostream>
  4. using namespace std;
  5. //Hash function you provided must be correspond to the type of the Key
  6. class HashFunc
  7. {
  8. public:
  9. int operator()(const string & key )
  10. {
  11. int hash = 0;
  12. for(int i = 0; i < key.length(); ++i)
  13. {
  14. hash = hash << 7 ^ key[i];
  15. }
  16. return (hash & 0x7FFFFFFF);
  17. }
  18. };
  19. //Equal function you provided to check whether two Keys are equal
  20. //must be correspond to the type of the Key
  21. class EqualKey
  22. {
  23. public:
  24. bool operator()(const string & A ,const string & B)
  25. {
  26. if(A.compare(B) == 0)
  27. return true; //if equal return true
  28. else
  29. return false; //else false
  30. }
  31. };
  32. int main()
  33. {
  34. HashMap<string,string,HashFunc,EqualKey> hm;
  35. hm.insert("hello" , "you");
  36. hm.insert("why" , "dream");
  37. hm.insert("java" ,"good");
  38. hm.insert("welcome" ,"haha");
  39. hm.insert("welcome" ,"hehe"); //error, key-value must be unique
  40. cout<<"after insert:"<<endl;
  41. cout<<hm.find("welcome")<<endl;
  42. cout<<hm.find("java")<<endl;
  43. cout<<hm["why"]<<endl;
  44. cout<<hm["hello"]<<endl;
  45. if(hm.remove("hello"))
  46. cout<<"remove is ok"<<endl; //remove is ok
  47. cout<<hm.find("hello")<<endl; //not exist print NULL
  48. hm["why"] = "love"; //modify the value
  49. cout<<hm["why"]<<endl;
  50. return 0;
  51. }

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

闽ICP备14008679号