Advertisement
Jacob_DiDiodato

dict.c

Feb 23rd, 2017
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.79 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <assert.h>
  3. #include <string.h>
  4.  
  5. #include "dict.h"
  6.  
  7. struct elt {
  8.     struct elt *next;
  9.     char *key;
  10.     char *value;
  11. };
  12.  
  13. struct dict {
  14.     int size;           /* size of the pointer table */
  15.     int n;              /* number of elements stored */
  16.     struct elt **table;
  17. };
  18.  
  19. #define INITIAL_SIZE (1024)
  20. #define GROWTH_FACTOR (2)
  21. #define MAX_LOAD_FACTOR (1)
  22.  
  23. /* dictionary initialization code used in both DictCreate and grow */
  24. Dict
  25. internalDictCreate(int size)
  26. {
  27.     Dict d;
  28.     int i;
  29.  
  30.     d = malloc(sizeof(*d));
  31.  
  32.     assert(d != 0);
  33.  
  34.     d->size = size;
  35.     d->n = 0;
  36.     d->table = malloc(sizeof(struct elt *) * d->size);
  37.  
  38.     assert(d->table != 0);
  39.  
  40.     for(i = 0; i < d->size; i++) d->table[i] = 0;
  41.  
  42.     return d;
  43. }
  44.  
  45. Dict
  46. DictCreate(void)
  47. {
  48.     return internalDictCreate(INITIAL_SIZE);
  49. }
  50.  
  51. void
  52. DictDestroy(Dict d)
  53. {
  54.     int i;
  55.     struct elt *e;
  56.     struct elt *next;
  57.  
  58.     for(i = 0; i < d->size; i++) {
  59.         for(e = d->table[i]; e != 0; e = next) {
  60.             next = e->next;
  61.  
  62.             free(e->key);
  63.             free(e->value);
  64.             free(e);
  65.         }
  66.     }
  67.  
  68.     free(d->table);
  69.     free(d);
  70. }
  71.  
  72. #define MULTIPLIER (97)
  73.  
  74. static unsigned long
  75. hash_function(const char *s)
  76. {
  77.     unsigned const char *us;
  78.     unsigned long h;
  79.  
  80.     h = 0;
  81.  
  82.     for(us = (unsigned const char *) s; *us; us++) {
  83.         h = h * MULTIPLIER + *us;
  84.     }
  85.  
  86.     return h;
  87. }
  88.  
  89. static void
  90. grow(Dict d)
  91. {
  92.     Dict d2;            /* new dictionary we'll create */
  93.     struct dict swap;   /* temporary structure for brain transplant */
  94.     int i;
  95.     struct elt *e;
  96.  
  97.     d2 = internalDictCreate(d->size * GROWTH_FACTOR);
  98.  
  99.     for(i = 0; i < d->size; i++) {
  100.         for(e = d->table[i]; e != 0; e = e->next) {
  101.             /* note: this recopies everything */
  102.             /* a more efficient implementation would
  103.              * patch out the strdups inside DictInsert
  104.              * to avoid this problem */
  105.             DictInsert(d2, e->key, e->value);
  106.         }
  107.     }
  108.  
  109.     /* the hideous part */
  110.     /* We'll swap the guts of d and d2 */
  111.     /* then call DictDestroy on d2 */
  112.     swap = *d;
  113.     *d = *d2;
  114.     *d2 = swap;
  115.  
  116.     DictDestroy(d2);
  117. }
  118.  
  119. /* insert a new key-value pair into an existing dictionary */
  120. void
  121. DictInsert(Dict d, const char *key, const char *value)
  122. {
  123.     struct elt *e;
  124.     unsigned long h;
  125.  
  126.     assert(key);
  127.     assert(value);
  128.  
  129.     e = malloc(sizeof(*e));
  130.  
  131.     assert(e);
  132.  
  133.     e->key = strdup(key);
  134.     e->value = strdup(value);
  135.  
  136.     h = hash_function(key) % d->size;
  137.  
  138.     e->next = d->table[h];
  139.     d->table[h] = e;
  140.  
  141.     d->n++;
  142.  
  143.     /* grow table if there is not enough room */
  144.     if(d->n >= d->size * MAX_LOAD_FACTOR) {
  145.         grow(d);
  146.     }
  147. }
  148.  
  149. /* return the most recently inserted value associated with a key */
  150. /* or 0 if no matching key is present */
  151. const char *
  152. DictSearch(Dict d, const char *key)
  153. {
  154.     struct elt *e;
  155.  
  156.     for(e = d->table[hash_function(key) % d->size]; e != 0; e = e->next) {
  157.         if(!strcmp(e->key, key)) {
  158.             /* got it */
  159.             return e->value;
  160.         }
  161.     }
  162.  
  163.     return 0;
  164. }
  165.  
  166. /* delete the most recently inserted record with the given key */
  167. /* if there is no such record, has no effect */
  168. void
  169. DictDelete(Dict d, const char *key)
  170. {
  171.     struct elt **prev;          /* what to change when elt is deleted */
  172.     struct elt *e;              /* what to delete */
  173.  
  174.     for(prev = &(d->table[hash_function(key) % d->size]);
  175.         *prev != 0;
  176.         prev = &((*prev)->next)) {
  177.         if(!strcmp((*prev)->key, key)) {
  178.             /* got it */
  179.             e = *prev;
  180.             *prev = e->next;
  181.  
  182.             free(e->key);
  183.             free(e->value);
  184.             free(e);
  185.  
  186.             return;
  187.         }
  188.     }
  189. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement