当前位置:   article > 正文

开散列法实现哈希桶_哈希散列值桶数

哈希散列值桶数

上节我们介绍了闭散列法实现哈希表的操作,今天我们来看开散列法实现哈希桶的操作。

开散列法(链地址法(开链法)

      开散列法首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点组成 一个向量,因此,向量的元素个数与可能的桶数一致。

设元素的关键码为37,25,14,36,49,68,57,11,散列表为HT[12],表的大小为12,散列函数为Hash(x) = x % 11   Hash(37)=4          Hash(25)=3      Hash(14)=3      Hash(36)=3

   Hash(49)=5      Hash(68)=2      Hash(57)=2      Hash(11)=0

 

通常,每个桶中的同义词子表都很短,设有n个关键码通过某一个散列函数,存放到散列表中的m个桶 中,那么每一个桶中的同义词子表的平均长度为n/m。这样以搜索平均长度为n/m的同义词子表代替了 搜索长度为n的顺序表,搜索效率快的多。

应用链地址法处理溢出,需要增设链接指针,似乎增加了存储开销。事实上,由于开地址法必须保持 大量的空闲空间以确保搜索效率,如二次探查法要求装载因子a <= 0.7 而表项所占空间又比指针大 的多,所以使用链地址法反而比开地址法节省存储空间。

在此次操作中,我们对关键元素key 和 下标value 值用键值对(pair<K,V>)进行封装,并对程序加入了迭代器,增加了难度。

但是原理不变。

(1)仿函数

  1. class KeyToIntDef
  2. {
  3. public:
  4. size_t operator()(const size_t& key)
  5. {
  6. return key;
  7. }
  8. };
  9. class stringToInt
  10. {
  11. public:
  12. size_t operator()(const string& key)
  13. {
  14. return BKDRHash(key.c_str());
  15. }
  16. private:
  17. static size_t BKDRHash(const char* str)
  18. {
  19. unsigned int seed = 131;
  20. unsigned int hash = 0;
  21. while (*str)
  22. {
  23. hash = hash*seed + (*str++);
  24. }
  25. return (hash & 0x7FFFFFFF);
  26. }
  27. };

(2)素数表增容

  1. const int _PriSize = 28;
  2. static size_t GetNextPrime(const size_t& value)
  3. {
  4. static const unsigned long _PrimeList[_PriSize] =
  5. {
  6. 53ul, 97ul, 193ul, 389ul, 769ul,
  7. 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
  8. 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
  9. 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
  10. 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
  11. 1610612741ul, 3221225473ul, 4294967291ul
  12. };
  13. for (int i = 0; i < _PriSize; i++)
  14. {
  15. if (_PrimeList[i]>value)
  16. return _PrimeList[i];
  17. }
  18. return _PrimeList[_PriSize - 1];
  19. }

(3)哈希桶的结点元素

  1. template<class K, class V>
  2. struct HashBucketNode
  3. {
  4. HashBucketNode(const pair<K, V>& key)
  5. :_key(key)
  6. , _PNext(NULL)
  7. {}
  8. pair<K, V> _key;
  9. HashBucketNode<K, V>* _PNext;
  10. };

(4)迭代器对指针的封装

包括构造函数,拷贝构造函数,前置++,后置++,->的重载,*的重载,判断是否相等或不相等等操作;

  1. //迭代器
  2. template<class K,class V,class KToInt>
  3. class HashBucketIterator
  4. {
  5. typedef HashBucketNode<K, V> Node;
  6. typedef Node* PNode;
  7. typedef HashBucketIterator<K, V, KToInt> IteratorSelf;
  8. public:
  9. PNode _Pcur; //迭代器成员变量
  10. HashBucket<K, V, KToInt>* _hb; //指向哈希表的指针
  11. public:
  12. HashBucketIterator()
  13. :_Pcur(NULL)
  14. ,_hb(NULL)
  15. {}
  16. HashBucketIterator(const PNode pcur, HashBucket<K, V, KToInt>*hb)
  17. :_Pcur(pcur)
  18. , _hb(hb)
  19. {}
  20. HashBucketIterator(const IteratorSelf& s)
  21. :_Pcur(s._Pcur)
  22. , _hb(s._hb)
  23. {}
  24. IteratorSelf& operator++()
  25. {
  26. Next();
  27. return *this;
  28. }
  29. IteratorSelf operator++(int)
  30. {
  31. IteratorSelf temp(*this);
  32. Next();
  33. return temp;
  34. }
  35. pair<K, V>& operator*()
  36. {
  37. return _Pcur->_key;
  38. }
  39. pair<K, V>* operator->()
  40. {
  41. return &(operator*());
  42. }
  43. bool operator==(const IteratorSelf& s)
  44. {
  45. return _Pcur == s._Pcur;
  46. }
  47. bool operator != (const IteratorSelf& s)
  48. {
  49. return !(operator==(s));
  50. }
  51. private:
  52. void Next()
  53. {
  54. if (_Pcur->_PNext)
  55. _Pcur = _Pcur->_PNext;
  56. else
  57. {
  58. //找下一个哈希桶
  59. size_t bucketNo = _hb->HashFunc(_Pcur->_key.first) + 1;
  60. for (; bucketNo < _hb->BucketCount(); bucketNo++)
  61. {
  62. if (_hb->_table[bucketNo])
  63. {
  64. _Pcur = _hb->_table[bucketNo];
  65. return;
  66. }
  67. }
  68. _Pcur = NULL;
  69. }
  70. return;
  71. }
  72. };

(5)哈希桶的实现

  1. template<class K,class V,class KToInt>
  2. class HashBucket
  3. {
  4. typedef HashBucketNode<K, V> Node;
  5. typedef Node* PNode;
  6. friend HashBucketIterator<K, V, KToInt>;
  7. public:
  8. typedef HashBucketIterator<K, V, KToInt> Iterator;
  9. public:
  10. HashBucket( size_t capacity=10)
  11. :_size(0)
  12. {
  13. capacity = GetNextPrime(capacity);
  14. _table.resize(capacity);
  15. }
  16. Iterator Begin()
  17. {
  18. for (size_t bucketNo = 0; bucketNo < _table.capacity(); ++bucketNo)
  19. {
  20. if (_table[bucketNo])
  21. return Iterator(_table[bucketNo], this);
  22. }
  23. return Iterator(NULL, this);
  24. }
  25. Iterator End()
  26. {
  27. return Iterator(NULL, this);
  28. }
  29. //插入重复元素
  30. pair<Iterator, bool> InsertEqual(const pair<K, V>& key)
  31. {
  32. CheckCapacity();
  33. size_t addre = HashFunc(key.first);
  34. PNode pcur = _table[addre];
  35. PNode newNode = new Node(key);
  36. //头插
  37. newNode->_PNext = pcur;
  38. _table[addre] = newNode;
  39. _size++;
  40. return make_pair(Iterator(newNode, this), true);
  41. }
  42. //插入唯一元素
  43. pair<Iterator, bool> InsertUnique(const pair<K, V>& key)
  44. {
  45. CheckCapacity();
  46. size_t addre = HashFunc(key.first);
  47. PNode pcur = _table[addre];
  48. //查找是否有相同元素
  49. while (pcur)
  50. {
  51. if (pcur->_key.first == key.first)
  52. return make_pair(Iterator(NULL,this), false);
  53. pcur = pcur->_PNext;
  54. }
  55. //插入结点
  56. PNode newNode = new Node(key);
  57. newNode->_PNext = _table[addre];
  58. _table[addre] = newNode;
  59. _size++;
  60. return make_pair(Iterator(newNode, this), true);
  61. }
  62. //查找元素
  63. Iterator Find(const pair<K,V>& key)
  64. {
  65. size_t addre = HashFunc(key.first);
  66. PNode pcur = _table[addre];
  67. while (pcur)
  68. {
  69. if (pcur->_key.first == key.first)
  70. return Iterator(pcur, this);
  71. pcur = pcur->_PNext;
  72. }
  73. return Iterator(NULL, this);
  74. }
  75. //删除唯一元素
  76. pair<Iterator, bool> EraseUnique(const pair<K, V>& key)
  77. {
  78. size_t addre = HashFunc(key.first);
  79. PNode pcur = _table[addre];
  80. PNode pre = NULL;
  81. if (_table[addre] == NULL)
  82. return make_pair(Iterator(NULL, this), false);
  83. while (pcur)
  84. {
  85. if (pcur->_PNext->_key.first == key.first)
  86. {
  87. if (pcur == _table[addre])
  88. {
  89. _table[addre] = NULL;
  90. }
  91. else
  92. {
  93. pre->_PNext = pcur->_PNext;
  94. }
  95. delete pcur;
  96. pcur = NULL;
  97. --size;
  98. return make_pair(Iterator(pre, this), true);
  99. }
  100. pre = pcur;
  101. pcur = pcur->_PNext;
  102. }
  103. return make_pair(Iterator(NULL, this), false);
  104. }
  105. //删除值不唯一
  106. pair<Iterator, bool> EraseEqual(const pair<K, V>& key)
  107. {
  108. size_t addre = HashFunc(key.first);
  109. PNode pcur = _table[addre];
  110. PNode pre = NULL;
  111. if (_table[addre] == NULL)
  112. return make_pair(Iterator(NULL, this), false);
  113. while (pcur)
  114. {
  115. if (pcur->_key.first == key.first)
  116. {
  117. if (pcur == _table[addre])
  118. {
  119. _table[addre] = pcur->_PNext;
  120. delete pcur;
  121. pcur = NULL;
  122. }
  123. else
  124. {
  125. pre->_PNext = pcur->_PNext;
  126. delete pcur;
  127. pcur = pcur->_PNext;
  128. }
  129. _size--;
  130. }
  131. else
  132. {
  133. pre = pcur;
  134. pcur = pre->_PNext;
  135. }
  136. }
  137. return make_pair(Iterator(NULL, this), false);
  138. }
  139. //值为key 的元素个数
  140. size_t Count(const pair<K, V>& key)
  141. {
  142. size_t addre = HashFunc(key.first);
  143. size_t count = 0;
  144. PNode pcur = _table[addre];
  145. while (pcur)
  146. {
  147. if (pcur->_key.first == key.first)
  148. count++;
  149. pcur = pcur->_PNext;
  150. }
  151. return count;
  152. }
  153. //桶的个数
  154. size_t BucketCount()const
  155. {
  156. return _table.capacity();
  157. }
  158. //桶内元素的个数
  159. size_t BucketElemSize(size_t bucketNo)const
  160. {
  161. size_t count = 0;
  162. PNode pcur = _table[bucketNo];
  163. while (pcur)
  164. {
  165. count++;
  166. pcur = pcur->_PNext;
  167. }
  168. return count;
  169. }
  170. //查找值为key,如果找到了,返回对应的value;如果没有找到,则插入该节点,返回缺省的value。
  171. V& FindOrInsert(const pair<K,V>& key)
  172. {
  173. size_t addre = HashFunc(key.first);
  174. PNode pcur = _table[addre];
  175. while (pcur)
  176. {
  177. if (pcur->_key.first == key.first)
  178. return pcur->_key.second;
  179. pcur = pcur->_PNext;
  180. }
  181. pair<Iterator, bool> ret = InsertUnique(make_pair(key.first, V()));
  182. return (*(ret.first)).second;
  183. }
  184. //判断是否为空
  185. bool Empty()const
  186. {
  187. return _size == 0;
  188. }
  189. //插入的总数
  190. size_t numsize()const
  191. {
  192. return _size;
  193. }
  194. //清空
  195. void clear()
  196. {
  197. for (size_t bucketNo = 0; bucketNo < _table.capacity(); ++bucketNo)
  198. {
  199. PNode pcur = _table[bucketNo];
  200. while (pcur)
  201. {
  202. PNode pDel = pcur->_PNext;
  203. delete pcur;
  204. pcur = pDel;
  205. _size--;
  206. }
  207. }
  208. }
  209. ~HashBucket()
  210. {
  211. clear();
  212. }
  213. private:
  214. void CheckCapacity()
  215. {
  216. size_t capacity = _table.capacity();
  217. if (_size==capacity)
  218. {
  219. size_t newcapacity = GetNextPrime(capacity);
  220. HashBucket<K, V, KToInt> hb(newcapacity);
  221. for (size_t bucketNo = 0; bucketNo < capacity; bucketNo++)
  222. {
  223. PNode pcur = _table[bucketNo];
  224. while (pcur)
  225. {
  226. hb.InsertEqual(pcur->_key);
  227. pcur = pcur->_PNext;
  228. }
  229. }
  230. swap(hb._table, _table);
  231. _size = hb._size;
  232. }
  233. }
  234. size_t HashFunc(const K& key)
  235. {
  236. return KToInt()(key) % _table.capacity();
  237. }
  238. private:
  239. vector<PNode> _table;
  240. size_t _size;
  241. };

(6)测试函数

  1. void test()
  2. {
  3. HashBucket<int, int, KeyToIntDef> hb(20);
  4. hb.InsertUnique(make_pair(2,2));
  5. hb.InsertUnique(make_pair(3, 3));
  6. hb.InsertUnique(make_pair(4, 4));
  7. hb.InsertUnique(make_pair(2, 5));
  8. /*hb.InsertEqual(make_pair(3, 3));
  9. hb.InsertEqual(make_pair(3, 4));
  10. hb.EraseEqual(make_pair(3, 3));*/
  11. /*cout<<hb.FindOrInsert(make_pair(2, 2));
  12. cout << hb.FindOrInsert(make_pair(9, 2));*/
  13. HashBucket<int, int, KeyToIntDef>::Iterator it = hb.Begin();
  14. if (!hb.Empty())
  15. {
  16. while (it != hb.End())
  17. {
  18. cout << it->first << " ";
  19. cout << (*it).second << endl;
  20. it++;
  21. }
  22. cout << hb.BucketCount();
  23. cout << hb.numsize();
  24. }
  25. //HashBucket<string, string, stringToInt>hb2(20);
  26. //hb2.InsertUnique(make_pair("1111", "1111"));
  27. //hb2.InsertUnique(make_pair("2222", "2222"));
  28. //hb2.InsertUnique(make_pair("3333", "3333"));
  29. //hb2.InsertUnique(make_pair("2222", "1111"));
  30. //cout << hb2.BucketCount();
  31. //cout << hb2.numsize();
  32. cout << hb2.FindOrInsert(make_pair("2222", "2222"));
  33. cout << hb2.FindOrInsert(make_pair("4444", "4444"));
  34. }

大家可以自己利用哈希桶封装unordered_map啊!

 

 

 

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

闽ICP备14008679号