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 }

 

posted @ 2018-09-08 01:51  我在地狱  阅读(356)  评论(0编辑  收藏  举报