hashtable
参考《stl源码剖析》,用开链法实现了简易hash表,并进行了简单测试。
特点:
1. hash表可扩容。当元素个数大于hash表长的时候,hash表挑选下一个质数,扩容一倍。
2. 提供了hash函数以及equal函数的载入
3. 提供find,insert,erase三个基本操作。
find返回某一元素的指针
insert可选择不重复插入或可重复插入
erase可选择删除一个元素或所有元素
4. 省略了迭代器,静态数组未封装在类内
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 namespace ht { 5 const int _num_prime = 22; 6 static const int prime_list[_num_prime] = { 7 53, 97, 193, 389, 769, 8 1543, 3079, 6151, 12289, 24593, 9 49157, 98317, 196613, 393241, 786433, 10 1572869, 3145739, 6291469, 12582917, 25165843, 11 50331653, 100663319 12 }; 13 14 template<class Value> 15 struct hashtable_node { 16 Value val; 17 hashtable_node *next; 18 hashtable_node(Value val, hashtable_node *next):val(val), next(next){} 19 }; 20 /* 21 template<class Key> 22 struct hashtable_iterator { 23 typedef hashtable_node<Key> node; 24 node *cur; 25 }; 26 */ 27 template<class Key, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>> 28 struct hashtable{ 29 typedef hashtable_node<Key> node; 30 31 Hash hash; 32 KeyEqual equals; 33 34 vector<node*> buckets; 35 int num_elements; 36 37 hashtable(int n = *prime_list){ 38 num_elements = 0; 39 int n_buckets = next_size(n); 40 buckets.resize(n_buckets); 41 } 42 ~hashtable(){ 43 for(auto cur: buckets) { 44 while(cur != NULL) { 45 node *tmp = cur->next; 46 delete cur; 47 cur = tmp; 48 } 49 } 50 } 51 52 node* find(const Key& obj) { 53 int n = hash(obj)%buckets.size(); 54 node *cur = buckets[n]; 55 while(cur) { 56 if (equals(cur->val, obj)) 57 return cur; 58 cur = cur->next; 59 } 60 return cur; 61 } 62 63 pair<node*, bool> insert(const Key& obj, bool same = false) { 64 resize(num_elements + 1); 65 const int n = hash(obj)%buckets.size(); 66 node *first = buckets[n], *tmp = NULL; 67 if(same || (tmp = find(obj)) == NULL) { 68 tmp = new node(obj, first); 69 buckets[n] = tmp; 70 ++num_elements; 71 return {tmp, true}; 72 } 73 return {tmp, false}; 74 } 75 76 bool erase(const Key& obj, bool same = false) { 77 if(find(obj) == NULL) return false; 78 int n = hash(obj)%buckets.size(); 79 node **cur = &buckets[n]; 80 while(*cur) { 81 if(equals((**cur).val, obj)) { 82 node *tmp = *cur; 83 *cur = tmp->next; 84 delete tmp; 85 --num_elements; 86 if(!same) break ; 87 } 88 else cur = &(**cur).next; 89 } 90 return true; 91 } 92 93 void debug() { 94 puts("debug..."); 95 bool tag = false; 96 for(auto cur: buckets) { 97 tag = false; 98 while(cur) { 99 tag = true; 100 printf("%d ", cur->val); 101 cur = cur->next; 102 } 103 if(tag) puts(""); 104 } 105 puts("end debug..."); 106 } 107 108 private: 109 int next_size(int n) { 110 const int *last = prime_list+_num_prime; 111 const int *pos = lower_bound(prime_list, last, n); 112 return pos == last? *(last-1) : *pos; 113 } 114 void resize(int num) { 115 int old_n = buckets.size(); 116 if(num > old_n){ 117 int n = next_size(num); 118 if(n > old_n){ 119 vector<node*> tmp(n, NULL); 120 for(int bucket = 0; bucket < old_n; ++bucket){ 121 node *first = buckets[bucket]; 122 while(first){ 123 int new_bucket = hash(first->val)%n; 124 buckets[bucket] = first->next; 125 first->next = tmp[new_bucket]; 126 tmp[new_bucket] = first; 127 first = buckets[bucket]; 128 } 129 } 130 buckets.swap(tmp); 131 } 132 } 133 } 134 }; 135 } 136 137 int main() { 138 ht::hashtable<int> H; 139 140 H.insert(3); 141 H.insert(3, true); 142 H.insert(3, true); 143 H.insert(3, true); 144 H.insert(3); 145 H.debug(); 146 printf("%d\n", H.erase(3)); 147 H.debug(); 148 149 auto p = H.find(3); 150 printf("%d\n",p? p->val: (int)p); 151 printf("%d\n", H.erase(3, true)); 152 153 p = H.find(3); 154 printf("%d\n",p? p->val: (int)p); 155 156 H.insert(3); 157 H.insert(3, true); 158 H.insert(3, true); 159 H.insert(3); 160 161 H.insert(5); 162 H.insert(5); 163 H.debug(); 164 p = H.find(5); 165 printf("%d\n",p? p->val: (int)p); 166 167 printf("%d\n", H.erase(5)); 168 printf("%d\n", H.erase(3)); 169 p = H.find(5); 170 printf("%d\n",p? p->val: (int)p); 171 H.debug(); 172 return 0; 173 }
诸神对凡人心生艳羡,厌倦天堂。