The hash table now automatically resizes when it gets full.
authorDavid Given <dg@cowlark.com>
Fri, 16 Dec 2016 17:09:58 +0000 (18:09 +0100)
committerDavid Given <dg@cowlark.com>
Fri, 16 Dec 2016 17:09:58 +0000 (18:09 +0100)
modules/src/data/bigraph.c
modules/src/data/hashtable.c
modules/src/data/hashtable.h

index d172a74..cc8440b 100644 (file)
@@ -120,6 +120,9 @@ void graph_add_edge(struct graph* g, void* data1, void* data2)
     struct vertex* v2 = find_or_add_vertex(g, data2);
     struct edgenode* e;
 
+       if (v1 == v2)
+               return;
+
     add_edge(v1, v2);
     e = add_edge(v2, v1);
 
index ebaae3b..7c895b5 100644 (file)
@@ -7,7 +7,7 @@ struct hashnode
 {
     struct hashnode* next;
     void* key;
-    void* data;
+    void* value;
 };
 
 uint32_t standard_pointer_hash_function(void* key)
@@ -46,6 +46,31 @@ void hashtable_reset(struct hashtable* ht)
     ht->buckets = NULL;
 }
 
+void hashtable_rebucket(struct hashtable* ht, unsigned int num_buckets)
+{
+    struct hashnode** old_buckets = ht->buckets;
+       int old_num_buckets = ht->num_buckets;
+       int i;
+       
+       ht->num_buckets = num_buckets;
+       ht->buckets = calloc(num_buckets, sizeof(struct hashnode*));
+
+       for (i=0; i<old_num_buckets; i++)
+       {
+               while (old_buckets[i])
+               {
+                       struct hashnode* hn = old_buckets[i];
+                       uint32_t hash = ht->hashfunction(hn->key) % num_buckets;
+
+                       old_buckets[i] = hn->next;
+                       hn->next = ht->buckets[hash];
+                       ht->buckets[hash] = hn;
+               }
+       }
+
+       free(old_buckets);
+}
+
 static struct hashnode** findnodep(struct hashtable* ht, void* key)
 {
     uint32_t hash;
@@ -61,27 +86,33 @@ static struct hashnode** findnodep(struct hashtable* ht, void* key)
     return hnp;
 }
 
-void* hashtable_put(struct hashtable* ht, void* key, void* data)
+void* hashtable_put(struct hashtable* ht, void* key, void* value)
 {
-    void* olddata;
+    void* oldvalue;
     struct hashnode** hnp = findnodep(ht, key);
     if (!*hnp)
     {
+               if (ht->size == (ht->num_buckets*2))
+               {
+                       hashtable_rebucket(ht, ht->num_buckets*3 + 1);
+                       return hashtable_put(ht, key, value);
+               }
+
         *hnp = calloc(1, sizeof(struct hashnode));
         ht->size++;
     }
 
-    olddata = (*hnp)->data;
+    oldvalue = (*hnp)->value;
     (*hnp)->key = key;
-    (*hnp)->data = data;
-    return olddata;
+    (*hnp)->value = value;
+    return oldvalue;
 }
 
 void* hashtable_get(struct hashtable* ht, void* key)
 {
     struct hashnode** hnp = findnodep(ht, key);
     if (*hnp)
-        return (*hnp)->data;
+        return (*hnp)->value;
     return NULL;
 }
 
@@ -119,11 +150,11 @@ void* hashtable_pop(struct hashtable* ht)
         if (*hnp)
         {
             struct hashnode* hn = *hnp;
-            void* data = hn->data;
+            void* value = hn->value;
             *hnp = hn->next;
             free(hn);
             ht->size--;
-            return data;
+            return value;
         }
     }
 
@@ -136,7 +167,7 @@ void* hashtable_next(struct hashtable* ht, struct hashtable_iterator* it)
     {
         if (it->bucket == ht->num_buckets)
         {
-            it->data = NULL;
+            it->key = it->value = NULL;
             it->bucket = 0;
             it->node = NULL;
             return NULL;
@@ -149,10 +180,11 @@ void* hashtable_next(struct hashtable* ht, struct hashtable_iterator* it)
         it->bucket++;
     }
 
-    it->data = it->node->data;
+    it->key = it->node->key;
+       it->value = it->node->value;
     it->node = it->node->next;
     if (!it->node)
         it->bucket++;
 
-    return it->data;
+    return it->value;
 }
index dac58c0..e89a052 100644 (file)
@@ -21,7 +21,8 @@ struct hashtable
 struct hashtable_iterator
 {
     /* Public */
-    void* data;
+    void* key;
+       void* value;
 
     /* Private */
     int bucket;
@@ -29,6 +30,7 @@ struct hashtable_iterator
 };
 
 extern void hashtable_reset(struct hashtable* ht);
+extern void hashtable_rebucket(struct hashtable* ht, unsigned int num_buckets);
 
 extern void* hashtable_put(struct hashtable* ht, void* key, void* data);
 extern void* hashtable_get(struct hashtable* ht, void* key);