• Source
    1. //假设我们要在 hashtable 中存的 key 和 value 都是数字
    2.  
    3. #include <iostream>
    4. #include <assert.h>
    5. using namespace std;
    6.  
    7. #define MIN_LOAD_FACTOR_THREHOLD 0.25
    8. #define MAX_LOAD_FACTOR_THREHOLD (MIN_LOAD_FACTOR_THREHOLD * 2)
    9. #define MIN_TABLE_SIZE 10
    10. #define MAX_TABLE_SIZE 100
    11.  
    12.  
    13. class Entry {
    14. private:
    15. int key;
    16. int value;
    17. public:
    18. Entry (int key, int value);
    19. int getKey ();
    20. int getValue ();
    21. };
    22.  
    23. Entry::Entry (int key, int value) {
    24. this->key = key;
    25. this->value = value;
    26. }
    27.  
    28. int Entry::getKey () {
    29. return this->key;
    30. }
    31.  
    32. int Entry::getValue () {
    33. return this->value;
    34. }
    35.  
    36. class Hashtable {
    37. private:
    38. int size;
    39. Entry **table;
    40. //已占用的位置个数
    41. int occupiedSize;
    42. //负载率临界值
    43. float minLoadFactorThreshold;
    44. float maxLoadFactorThreshold;
    45. int maxTableSize;
    46. int minTableSize;
    47. static Entry * deleteEntry;
    48. void resize(double factor);
    49.  
    50. public:
    51. Hashtable (int size);
    52. int get (int key);
    53. void put (int key, int value);
    54. int hash (int key);
    55. int getSize ();
    56. int getOccupiedSize ();
    57. void remove (int key);
    58. ~Hashtable ();
    59. };
    60.  
    61. Entry * Hashtable::deleteEntry = new Entry(-1, -1);
    62.  
    63. Hashtable::Hashtable (int size) {
    64. assert(size > 0);
    65. this->size = size;
    66. occupiedSize = 0;
    67. minTableSize = MIN_TABLE_SIZE;
    68. maxTableSize = MAX_TABLE_SIZE;
    69. minLoadFactorThreshold = MIN_LOAD_FACTOR_THREHOLD;
    70. maxLoadFactorThreshold = MAX_LOAD_FACTOR_THREHOLD;
    71. table = new Entry* [size];
    72. for (int i = 0; i < size; i++) {
    73. table[i] = NULL;
    74. }
    75. }
    76.  
    77. void Hashtable::put (int key, int value) {
    78. int hash = this->hash(key);
    79. int count = 0;
    80. while(table[hash] != NULL) {
    81. //全部位置遍历后,如果仍然没有空位,返回;
    82. if (count >= size) {
    83. cout << "The hashtable is full, failed to add {key:" << key << " value:" << value << "}" << endl;
    84. return;
    85. }
    86. hash = (hash + 1) % size;
    87. count ++;
    88. }
    89. table[hash] = new Entry(key, value);
    90. occupiedSize ++;
    91. float currentLoadFactor = (float)occupiedSize / (float)size;
    92. if( currentLoadFactor > maxLoadFactorThreshold && size * 2 < maxTableSize) {
    93. resize(2);
    94. }
    95. }
    96.  
    97. int Hashtable::get (int key) {
    98. int hash = this->hash(key);
    99. int count = 0;
    100. while(table[hash] != NULL) {
    101. if(table[hash]->getKey() == key) {
    102. return table[hash]->getValue();
    103. }
    104. //全部位置遍历后,仍然没有找到对应的key,返回-1
    105. if (count >= size) {
    106. return -1;
    107. }
    108. hash = (hash + 1) % size;
    109. count ++;
    110. }
    111.  
    112. return -1;
    113. }
    114.  
    115. int Hashtable::hash (int key) {
    116. return key % size;
    117. }
    118. int Hashtable::getSize () {
    119. return size;
    120. }
    121. int Hashtable::getOccupiedSize () {
    122. return occupiedSize;
    123. }
    124.  
    125. void Hashtable::resize (double factor) {
    126. int oldSize = size;
    127. Entry ** oldTable = table;
    128. size = (int) oldSize * factor;
    129. table = new Entry* [size];
    130. occupiedSize = 0;
    131.  
    132. for (int i = 0; i < size; i++) {
    133. table[i] = NULL;
    134. }
    135.  
    136.  
    137. for (int i = 0; i < oldSize; i++) {
    138. if (NULL != oldTable[i] && oldTable[i] != deleteEntry) {
    139. put(oldTable[i]->getKey(), oldTable[i]->getValue());
    140. }
    141. }
    142.  
    143. delete[] oldTable;
    144.  
    145. }
    146.  
    147. void Hashtable::remove (int key) {
    148. int hash = this->hash(key);
    149. int count = 0;
    150. while(table[hash] != NULL) {
    151. if(table[hash]->getKey() == key) {
    152. delete table[hash];
    153. table[hash] = deleteEntry;
    154. occupiedSize --;
    155. // cout << "remove and occupiedSize: " << occupiedSize << endl;
    156. float currentLoadFactor = (float)occupiedSize / (float)size;
    157. if( currentLoadFactor < minLoadFactorThreshold && size / 2 > minTableSize) {
    158. resize(0.5);
    159. }
    160.  
    161. }
    162. //全部位置遍历后,仍然没有找到对应的key
    163. if (count >= size) {
    164. cout << "没有找到你要删除的 key: " << key << endl;
    165. return;
    166. }
    167. hash = (hash + 1) % size;
    168. count ++;
    169. }
    170. }
    171.  
    172. Hashtable::~Hashtable () {
    173. for (int i = 0; i < size; i++) {
    174. if(table[i]) {
    175. delete table[i];
    176. }
    177. }
    178. delete [] table;
    179. }
    180.  
    181. int main () {
    182. Hashtable * table10 = new Hashtable(10);
    183. table10->put(1, 100);
    184. table10->put(2, 200);
    185. table10->put(3, 300);
    186. assert(table10->get(1) == 100);
    187. assert(table10->get(2) == 200);
    188. assert(table10->get(3) == 300);
    189. assert(table10->getSize() == 10);
    190. assert(table10->getOccupiedSize() == 3);
    191.  
    192.  
    193. //测试当负载率大于maxLoadFactorThreshold,要扩大 size * 2
    194. Hashtable * table2 = new Hashtable(2);
    195. table2->put(1, 100);
    196. table2->put(2, 200);
    197. table2->put(3, 300);
    198. assert(table2->get(1) == 100);
    199. assert(table2->get(2) == 200);
    200. assert(table2->get(3) == 300);
    201. assert(table2->getSize() == 8);
    202. assert(table2->getOccupiedSize() == 3);
    203.  
    204.  
    205. //测试删除和最小删除值
    206. Hashtable * table11 = new Hashtable(11);
    207. table11->put(1, 100);
    208. table11->put(2, 200);
    209. table11->put(3, 300);
    210. table11->put(4, 400);
    211. table11->put(5, 500);
    212. table11->put(6, 600);
    213. table11->put(7, 700);
    214. table11->put(8, 800);
    215. table11->put(9, 900);
    216. table11->put(10, 1000);
    217. table11->put(11, 1100);
    218. table11->put(12, 1200);
    219. assert(table11->get(8) == 800);
    220. assert(table11->getSize() == 44);
    221. assert(table11->getOccupiedSize() == 12);
    222. table11->remove(8);
    223. assert(table11->get(8) == -1);
    224. table11->remove(7);
    225. // 10 / 44 = 0.2 0.2 < 0.25 所以要压缩
    226. assert(table11->getSize() == 22);
    227. assert(table11->getOccupiedSize() == 10);
    228. table11->remove(6);
    229. table11->remove(5);
    230. table11->remove(4);
    231. table11->remove(3);
    232. table11->remove(2);
    233. // 5 / 22 = 0.2 0.2 < 0.25 所以要压缩
    234. assert(table11->getSize() == 11);
    235. assert(table11->getOccupiedSize() == 5);
    236. table11->remove(1);
    237. table11->remove(9);
    238. table11->remove(10);
    239. // 2 / 11 = 0.18 0.18 < 0.25 但是 11/2 < 10 ,所以不压缩
    240. assert(table11->getSize() == 11);
    241. assert(table11->getOccupiedSize() == 2);
    242.  
    243. cout << "The tests run successfully." << endl;
    244.  
    245. }