Очень простая реализация карты в C (для целей кэширования)? - PullRequest
7 голосов
/ 05 августа 2009

У меня есть программа, которая читает URL-адреса в файле и делает gethostbyname() на каждом хосте URL. Этот звонок довольно трудоемкий. Я хочу их кешировать.

Есть ли в C очень простой фрагмент кода на основе карты, который я мог бы использовать для кэширования? (Я просто не хочу изобретать велосипед).

Он должен иметь следующие пункты:

  • Открытый код с разрешительной лицензией (например, BSD или общественное достояние).
  • Очень просто: в идеале менее 100 LOC
  • Ключи char* и значения void*. Не нужно их копировать.
  • Нет необходимости в реализации remove(), но contains() либо необходим, либо put() должно заменить значение.

PS: я отметил это домашнее задание , так как это может быть. Я просто очень ленивый и хочу избежать всех распространенных ошибок, с которыми я могу столкнуться при повторной реализации.

Ответы [ 8 ]

5 голосов
/ 05 августа 2009

Вот очень простой и наивный

  • Фиксированный размер ковша
  • Нет операции удаления
  • вставляет заменяет ключ и значение и может по желанию освободить их

:

#include <string.h>
#include <stdlib.h>

#define NR_BUCKETS 1024

struct StrHashNode {
    char *key;
    void *value;
    struct StrHashNode *next;

};

struct StrHashTable {
    struct StrHashNode *buckets[NR_BUCKETS];
    void (*free_key)(char *);
    void (*free_value)(void*);
    unsigned int (*hash)(const char *key);
    int (*cmp)(const char *first,const char *second);
};

void *get(struct StrHashTable *table,const char *key)
{
    unsigned int bucket = table->hash(key)%NR_BUCKETS;
    struct StrHashNode *node;
    node = table->buckets[bucket];
    while(node) {
        if(table->cmp(key,node->key) == 0)
            return node->value;
        node = node->next;
    }
    return NULL;
}
int insert(struct StrHashTable *table,char *key,void *value)
{
    unsigned int bucket = table->hash(key)%NR_BUCKETS;
    struct StrHashNode **tmp;
    struct StrHashNode *node ;

    tmp = &table->buckets[bucket];
    while(*tmp) {
        if(table->cmp(key,(*tmp)->key) == 0)
            break;
        tmp = &(*tmp)->next;
    }
    if(*tmp) {
        if(table->free_key != NULL)
            table->free_key((*tmp)->key);
        if(table->free_value != NULL)
            table->free_value((*tmp)->value);
        node = *tmp;
    } else {
        node = malloc(sizeof *node);
        if(node == NULL)
            return -1;
        node->next = NULL;
        *tmp = node;
    }
    node->key = key;
    node->value = value;

    return 0;
}

unsigned int foo_strhash(const char *str)
{
    unsigned int hash = 0;
    for(; *str; str++)
        hash = 31*hash + *str;
    return hash;
}

#include <stdio.h>
int main(int argc,char *argv[])
{
    struct StrHashTable tbl = {{0},NULL,NULL,foo_strhash,strcmp};

    insert(&tbl,"Test","TestValue");
    insert(&tbl,"Test2","TestValue2");
    puts(get(&tbl,"Test"));
    insert(&tbl,"Test","TestValueReplaced");
    puts(get(&tbl,"Test"));

    return 0;
}
5 голосов
/ 05 августа 2009

Реализация хеш-таблицы Кристопера Кларка очень проста. Это более 100 строк, но не намного.

Код Кларка, похоже, проник в Библиотеку параллелизма Google в качестве примера параллелизации.

3 голосов
/ 05 августа 2009

std::map в C ++ - красно-черное дерево под капотом; как насчет использования существующей реализации красно-черного дерева в C ? Тот, который я связал, больше похож на 700 LOC, но он довольно хорошо прокомментирован и выглядит нормальным из беглого взгляда на него. Вы, вероятно, можете найти других; этот был первый хит в Google для "C красно-черное дерево".

Если вы не придирчивы к производительности, вы также можете использовать несбалансированное двоичное дерево, минимальную кучу или что-то в этом роде. При сбалансированном бинарном дереве вам гарантирован O (log n) поиск; с несбалансированным деревом наихудший случай для поиска - O (n) (для патологического случая, когда узлы вставляются по порядку, так что в итоге получается одна действительно длинная ветвь, которая действует как связанный список), но (если мой ржавый память верна) средний регистр все еще O (log n).

2 голосов
/ 12 апреля 2011

Вы можете попробовать использовать следующую реализацию

CLIB

1 голос
/ 05 августа 2009

Интерфейсы и реализации C Дейва Хэнсона включают в себя хорошую хэш-таблицу, а также множество других полезных модулей. Хеш-таблица имеет 150 строк, но это включает управление памятью, функцию отображения более высокого порядка и преобразование в массив. Программное обеспечение бесплатное, и книгу стоит купить.

1 голос
/ 05 августа 2009

Не ленивый, глубоко разумный, чтобы не писать этот материал.

Как эта библиотека никогда не использовала ее сама, но, кажется, заявляет, что делает то, что вы просите.

1 голос
/ 05 августа 2009

Memcached

Не фрагмент кода, а высокопроизводительный механизм распределенного кэширования.

0 голосов
/ 05 августа 2009

Здесь нашли реализацию: c файл и h файл, который довольно близок к тому, что вы просили. Лицензия W3C

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...