构造哈希表之二次探测法

原文链接: https://blog.csdn.net/xyzbaihaiping/article/details/51607770

HashTable-散列表/哈希表

是根据关键字(key)而直接访问在内存存储位置的数据结构。

它通过一个关键值的函数将所需的数据映射到表中的位置来访问数据,这个映射函数叫做散列(哈希)函数,存放记录的数组叫做散列表。

构造哈希表的几种方法
1.直接定址法(取关键字的某个线性函数为哈希地址)
2.除留余数法(取关键值被某个不大于散列表长m的数p除后的所得的余数为散列地址)
3.平方取中法
4.折叠法
5.随机数法
6.数学分析法
常用方法是 直接定址法除留余数法

哈希冲突/哈希碰撞
不同的Key值经过哈希函数Hash(Key)处理以后可能产生相同的值哈希地址,我们称这种情况为哈希冲突。任意的散列函数都不能避免产生冲突。

处理哈希碰撞的方法
若key1,key2,key3产生哈希冲突(key1,key2,key3值不相同,映射的哈希地址同为key),用以下方法确定它们的地址

1.闭散列法
1)线性探测
若当前key与原来key产生相同的哈希地址,则当前key存在该地址之后没有存任何元素的地址中
key1:hash(key)+0
key2:hash(key)+1
key3:hash(key)+2
例如:
构造哈希表之二次探测法_第1张图片
2)二次探测
若当前key与原来key产生相同的哈希地址,则当前key存在该地址后偏移量为(1,2,3...)的二次方地址处
key1:hash(key)+0
key2:hash(key)+1^2
key3:hash(key)+2^2
例如:

构造哈希表之二次探测法_第2张图片


2.开链法(哈希桶)
哈希表中保存包含每个key值的节点,每个节点有一个_next的指针,指向产生哈希冲突的key的节点
例如:
构造哈希表之二次探测法_第3张图片
具体实现方式请看下一篇博客,博客链接: http://blog.csdn.net/xyzbaihaiping/article/details/51610944

构建哈希表(二次探测法)
支持key值为字符串

    
    
    
    
  1. "code" class=
            
            
            
            "cpp">
            
            
            
            //HashTable.h
           
           
           
           
  2. #pragma once
  3. #include
  4. #include < string>
  5. using namespace std;
  6. enum State
  7. {
  8. EMPTY, //空
  9. EXITS, //存在
  10. DELETE //已删除
  11. };
  12. template< class K, class V>
  13. struct HashTableNode
  14. {
  15. K _key;
  16. V _value;
  17. };
  18. template< class K>
  19. struct _ HashFunc
  20. {
  21. size_t operator()( const K& key, const size_t& capacity) //哈希函数,仿函数
  22. {
  23. return key / capacity;
  24. }
  25. };
  26. template<>
  27. struct _HashFunc//模板特化
  28. {
  29. private:
  30. unsigned int _BKDRHash( const char *str) //key为字符串时哈希函数
  31. {
  32. unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
  33. unsigned int hash = 0;
  34. while (*str)
  35. {
  36. hash = hash * seed + (*str++);
  37. }
  38. return (hash & 0x7FFFFFFF);
  39. }
  40. public:
  41. size_t operator()( const string& key, const size_t& capacity) //仿函数
  42. {
  43. return _BKDRHash(key.c_str()) % capacity;
  44. }
  45. };
  46. template< class K, class V,class HashFunc=_HashFunc>
  47. class HashTable
  48. {
  49. typedef HashTableNode Node;
  50. public:
  51. HashTable( size_t capacity = 10)
  52. :_tables( new Node[capacity])
  53. , _states( new State[capacity])
  54. , _size( 0)
  55. , _capacity(capacity)
  56. {}
  57. ~HashTable()
  58. {
  59. if (_tables != NULL)
  60. {
  61. delete[] _tables;
  62. delete[] _states;
  63. }
  64. }
  65. HashTable( const HashTable& ht)
  66. {
  67. HashTable tmp(ht._capacity);
  68. for ( size_t i = 0; i < ht._capacity; i++)
  69. {
  70. tmp.Insert(ht._tables[i]._key, ht._tables[i]._value);
  71. }
  72. this->Swap(tmp);
  73. }
  74. HashTable& operator=(HashTable ht)
  75. {
  76. this->Swap();
  77. return * this;
  78. }
  79. bool Insert(const K& key, const V& value)
  80. {
  81. _CheckCapacity();
  82. size_t index = HashFunc()(key, _capacity);
  83. size_t i = 1;
  84. while (_states[index] == EXITS) //二次探测
  85. {
  86. if (_tables[index]._key == key)
  87. {
  88. return false;
  89. }
  90. index = index + 2 * i - 1;
  91. index %= _capacity;
  92. ++i;
  93. }
  94. _tables[index]._key = key;
  95. _tables[index]._value = value;
  96. _states[index] = EXITS;
  97. ++_size;
  98. return true;
  99. }
  100. bool Find(const K& key)
  101. {
  102. size_t index = HashFunc()(key, _capacity);
  103. size_t start = index;
  104. size_t i = 1;
  105. while (_states[index] != EMPTY) //根据二次探测法查找
  106. {
  107. if (_tables[index]._key == key)
  108. {
  109. if (_states[index] != DELETE)
  110. return true;
  111. else
  112. return false;
  113. }
  114. index = index + 2 * i - 1;
  115. index %= _capacity;
  116. if (start == index)
  117. return false;
  118. }
  119. return false;
  120. }
  121. bool Remove(const K& key)
  122. {
  123. size_t index = HashFunc()(key, _capacity);
  124. size_t start = index;
  125. size_t i = 1;
  126. while (_states[index] != EMPTY) //根据二次探测法删除
  127. {
  128. if (_tables[index]._key == key)
  129. {
  130. if (_states[index] != DELETE)
  131. {
  132. _states[index] = DELETE;
  133. _size--;
  134. return true;
  135. }
  136. else
  137. return false;
  138. }
  139. index = index + 2 * i - 1;
  140. index %= _capacity;
  141. if (start == index)
  142. return false;
  143. }
  144. return false;
  145. }
  146. void Print()
  147. {
  148. for ( size_t i = 0; i < _capacity; i++)
  149. {
  150. //printf("%d-[%s:%s] \n", _states[i], _tables[i]._key, _tables[i]._value);
  151. cout << _states[i] << " " << _tables[i]._key << " " << _tables[i]._value<< endl;
  152. }
  153. }
  154. private:
  155. void Swap(HashTable& tmp)
  156. {
  157. swap(_tables, tmp._tables);
  158. swap(_states, tmp._states);
  159. swap(_size, tmp._size);
  160. swap(_capacity, tmp._capacity);
  161. }
  162. void _CheckCapacity() //增容
  163. {
  164. if (_size * 10 / _capacity == 6)
  165. {
  166. HashTable tmp(_capacity * 2);
  167. for ( size_t i = 0; i < _capacity; i++)
  168. {
  169. if (_states[i] == EXITS)
  170. tmp.Insert(_tables[i]._key, _tables[i]._value);
  171. }
  172. this->Swap(tmp);
  173. }
  174. }
  175. private:
  176. Node* _tables; //哈希表
  177. State* _states; //状态表
  178. size_t _size;
  179. size_t _capacity;
  180. };


 
   

    
    
    
    
"1711228" snippet_file_name=
        
        
        
        "blog_20160608_3_3809584" name=
        
        
        
        "code" 
        
        
        
        class=
        
        
        
        "cpp">
        
        
        
        //test.cpp
       
       
       
       
  • #include
  • #include "HashTable.h"
  • void testInt()
  • {
  • HashTable<int, int> table(10);
  • table.Insert( 89, 89);
  • table.Insert( 18, 18);
  • table.Insert( 49, 49);
  • table.Insert( 58, 58);
  • table.Insert( 9, 9);
  • //table.Insert(45, 45);
  • //table.Insert(2, 2);
  • table.Print();
  • HashTable<int, int> table1(table);
  • table1.Print();
  • bool ret = table.Find( 9);
  • cout << endl << ret << endl;
  • table.Remove( 9);
  • table.Print();
  • }
  • void TestString()
  • {
  • HashTable<string, string> table(10);
  • table.Insert( "dict", "字典");
  • table.Insert( "hash", "哈希");
  • table.Insert( "function", "函数");
  • table.Insert( "abcd", "函数");
  • table.Insert( "dcba", "函数");
  • table.Print();
  • bool ret = table.Find( "function");
  • cout << endl << ret << endl;
  • table.Remove( "hash");
  • table.Print();
  • }
  • int main()
  • {
  • //testInt();
  • TestString();
  • getchar();
  • return 0;
  • }

  • 测试结果:
    构造哈希表之二次探测法_第4张图片

    你可能感兴趣的:(C++,算法)