# 哈希表的C实现（二）

struct Pair {    char *key;    char *value;};struct Bucket {    unsigned int count;    Pair *pairs;};struct StrMap {    unsigned int count;    Bucket *buckets;};

put：

int sm_put(StrMap *map, const char *key, const char *value){    unsigned int key_len, value_len, index;    Bucket *bucket;    Pair *tmp_pairs, *pair;    char *tmp_value;    char *new_key, *new_value;    if (map == NULL) {        return 0;    }    if (key == NULL || value == NULL) {        return 0;    }    key_len = strlen(key);    value_len = strlen(value);    /* Get a pointer to the bucket the key string hashes to */    index = hash(key) % map->count;    bucket = &(map->buckets[index]);    /* Check if we can handle insertion by simply replacing     * an existing value in a key-value pair in the bucket.     */    if ((pair = get_pair(bucket, key)) != NULL) {        /* The bucket contains a pair that matches the provided key,         * change the value for that pair to the new value.         */        if (strlen(pair->value) < value_len) {            /* If the new value is larger than the old value, re-allocate             * space for the new larger value.             */            tmp_value = realloc(pair->value, (value_len + 1) * sizeof(char));            if (tmp_value == NULL) {                return 0;            }            pair->value = tmp_value;        }        /* Copy the new value into the pair that matches the key */        strcpy(pair->value, value);        return 1;    }    /* Allocate space for a new key and value */    new_key = malloc((key_len + 1) * sizeof(char));    if (new_key == NULL) {        return 0;    }    new_value = malloc((value_len + 1) * sizeof(char));    if (new_value == NULL) {        free(new_key);        return 0;    }    /* Create a key-value pair */    if (bucket->count == 0) {        /* The bucket is empty, lazily allocate space for a single         * key-value pair.         */        bucket->pairs = malloc(sizeof(Pair));        if (bucket->pairs == NULL) {            free(new_key);            free(new_value);            return 0;        }        bucket->count = 1;    }    else {        /* The bucket wasn't empty but no pair existed that matches the provided         * key, so create a new key-value pair.         */        tmp_pairs = realloc(bucket->pairs, (bucket->count + 1) * sizeof(Pair));        if (tmp_pairs == NULL) {            free(new_key);            free(new_value);            return 0;        }        bucket->pairs = tmp_pairs;        bucket->count++;    }    /* Get the last pair in the chain for the bucket */    pair = &(bucket->pairs[bucket->count - 1]);    pair->key = new_key;    pair->value = new_value;    /* Copy the key and its value into the key-value pair */    strcpy(pair->key, key);    strcpy(pair->value, value);    return 1;}

get：

int sm_get(const StrMap *map, const char *key, char *out_buf, unsigned int n_out_buf){    unsigned int index;    Bucket *bucket;    Pair *pair;    if (map == NULL) {        return 0;    }    if (key == NULL) {        return 0;    }    index = hash(key) % map->count;    bucket = &(map->buckets[index]);    pair = get_pair(bucket, key);    if (pair == NULL) {        return 0;    }    if (out_buf == NULL && n_out_buf == 0) {        return strlen(pair->value) + 1;    }    if (out_buf == NULL) {        return 0;    }    if (strlen(pair->value) >= n_out_buf) {        return 0;    }    strcpy(out_buf, pair->value);    return 1;}

/* * Returns a hash code for the provided string. */static unsigned long hash(const char *str){    unsigned long hash = 5381;    int c;    while (c = *str++) {        hash = ((hash << 5) + hash) + c;    }    return hash;}

posted @ 2012-01-16 11:06  红心李  阅读(8596)  评论(3编辑  收藏  举报