Jacob_DiDiodato icon

dict.c

Jacob_DiDiodato | PRO | 02/24/17 12:39:26 AM UTC | 0 ⭐ | 310 👁️ | Never ⏰ | []
C |

3.79 KB

|

None

|

0 👍

/

0 👎

#include <stdlib.h>
#include <assert.h>
#include <string.h>
 
#include "dict.h"
 
struct elt {
    struct elt *next;
    char *key;
    char *value;
};
 
struct dict {
    int size;           /* size of the pointer table */
    int n;              /* number of elements stored */
    struct elt **table;
};
 
#define INITIAL_SIZE (1024)
#define GROWTH_FACTOR (2)
#define MAX_LOAD_FACTOR (1)
 
/* dictionary initialization code used in both DictCreate and grow */
Dict
internalDictCreate(int size)
{
    Dict d;
    int i;
 
    d = malloc(sizeof(*d));
 
    assert(d != 0);
 
    d->size = size;
    d->n = 0;
    d->table = malloc(sizeof(struct elt *) * d->size);
 
    assert(d->table != 0);
 
    for(i = 0; i < d->size; i++) d->table[i] = 0;
 
    return d;
}
 
Dict
DictCreate(void)
{
    return internalDictCreate(INITIAL_SIZE);
}
 
void
DictDestroy(Dict d)
{
    int i;
    struct elt *e;
    struct elt *next;
 
    for(i = 0; i < d->size; i++) {
        for(e = d->table[i]; e != 0; e = next) {
            next = e->next;
 
            free(e->key);
            free(e->value);
            free(e);
        }
    }
 
    free(d->table);
    free(d);
}
 
#define MULTIPLIER (97)
 
static unsigned long
hash_function(const char *s)
{
    unsigned const char *us;
    unsigned long h;
 
    h = 0;
 
    for(us = (unsigned const char *) s; *us; us++) {
        h = h * MULTIPLIER + *us;
    }
 
    return h;
}
 
static void
grow(Dict d)
{
    Dict d2;            /* new dictionary we'll create */
    struct dict swap;   /* temporary structure for brain transplant */
    int i;
    struct elt *e;
 
    d2 = internalDictCreate(d->size * GROWTH_FACTOR);
 
    for(i = 0; i < d->size; i++) {
        for(e = d->table[i]; e != 0; e = e->next) {
            /* note: this recopies everything */
            /* a more efficient implementation would
             * patch out the strdups inside DictInsert
             * to avoid this problem */
            DictInsert(d2, e->key, e->value);
        }
    }
 
    /* the hideous part */
    /* We'll swap the guts of d and d2 */
    /* then call DictDestroy on d2 */
    swap = *d;
    *d = *d2;
    *d2 = swap;
 
    DictDestroy(d2);
}
 
/* insert a new key-value pair into an existing dictionary */
void
DictInsert(Dict d, const char *key, const char *value)
{
    struct elt *e;
    unsigned long h;
 
    assert(key);
    assert(value);
 
    e = malloc(sizeof(*e));
 
    assert(e);
 
    e->key = strdup(key);
    e->value = strdup(value);
 
    h = hash_function(key) % d->size;
 
    e->next = d->table[h];
    d->table[h] = e;
 
    d->n++;
 
    /* grow table if there is not enough room */
    if(d->n >= d->size * MAX_LOAD_FACTOR) {
        grow(d);
    }
}
 
/* return the most recently inserted value associated with a key */
/* or 0 if no matching key is present */
const char *
DictSearch(Dict d, const char *key)
{
    struct elt *e;
 
    for(e = d->table[hash_function(key) % d->size]; e != 0; e = e->next) {
        if(!strcmp(e->key, key)) {
            /* got it */
            return e->value;
        }
    }
 
    return 0;
}
 
/* delete the most recently inserted record with the given key */
/* if there is no such record, has no effect */
void
DictDelete(Dict d, const char *key)
{
    struct elt **prev;          /* what to change when elt is deleted */
    struct elt *e;              /* what to delete */
 
    for(prev = &(d->table[hash_function(key) % d->size]); 
        *prev != 0; 
        prev = &((*prev)->next)) {
        if(!strcmp((*prev)->key, key)) {
            /* got it */
            e = *prev;
            *prev = e->next;
 
            free(e->key);
            free(e->value);
            free(e);
 
            return;
        }
    }
}

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎