C 中非常简单的地图实现(用于缓存目的)?

发布于 2024-07-30 18:58:19 字数 531 浏览 5 评论 0原文

我有一个程序可以读取文件中的 url,并在每个 URL 主机上执行 gethostbyname() 操作。 这个调用相当消耗。 我想缓存它们。

C 语言中是否有一个非常简单的基于地图的代码片段,我可以用它来进行缓存? (我只是不想重新发明轮子)。

它必须具备以下几点:

  • 具有宽松许可证的开源(想想 BSD 或公共领域)。
  • 非常简单:理想情况下少于 100 个 LOC
  • 键是 char* 和值 void*。 无需复制它们。
  • 没有真正需要实现 remove(),但需要 contains()put() 应该替换该值。

PS:我给它贴上了作业的标签,因为它可能是。 我只是非常懒惰,并且确实想避免重新实现时可能遇到的所有常见陷阱。

I have a program that read urls in a file and does a gethostbyname() on each URL host. This call is quite consuming. I want to cache them.

Is there a very simple map-base code snippet in C out there that I could use to do the caching? (I just don't want to reinvent the wheel).

It has to have the following points :

  • Open-source with a permissive license (think BSD or public domain).
  • Very simple : ideally less than 100 LOC
  • Keys are char* and values void*. No need to copy them.
  • No real need to implement remove(), but contains() is either needed or put() should replace the value.

PS: I tagged it homework, since it could be. I'm just being very lazy and do want to avoid all the common pitfalls I could encounter while reimplementing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

乖乖哒 2024-08-06 18:58:28

在这里找到了一个实现: c 文件和 h 文件与您所要求的非常接近。 W3C 许可证

Found an implementation here : c file and h file that's fairly close to what you asked. W3C license

执笔绘流年 2024-08-06 18:58:27

Dave Hanson 的 C 接口和实现 包含一个很好的哈希表,以及许多其他内容有用的模块。 哈希表有 150 行,但这包括内存管理、高阶映射函数和数组转换。 该软件是免费的,这本书值得购买。

Dave Hanson's C Interfaces and Implementations includes a nice hash table, as well as many other useful modules. The hash table clocks in at 150 lines, but that's including memory management, a higher-order mapping function, and conversion to array. The software is free, and the book is worth buying.

小忆控 2024-08-06 18:58:27

不是偷懒,而是非常明智地避免写这些东西。

这个 怎么样,我自己从未使用过它,但它似乎声称可以满足您的要求。

Not lazy, deeply sensible to avoid writing this stuff.

How's this library never used it myself but it seems to claim to do what you ask for.

煮茶煮酒煮时光 2024-08-06 18:58:26

memcached

不是代码片段,而是高性能分布式缓存引擎。

memcached?

Not a code snippet, but a high performance distributed caching engine.

苦行僧 2024-08-06 18:58:25

您可以尝试使用以下实现

clib

You can try using following implemntation

clib

甜点 2024-08-06 18:58:24

克里斯托弗·克拉克的哈希表的实现非常简单。 虽然有 100 多行,但也不是很多。

Clark 的代码似乎已进入 Google 的并发库作为并行化示例。

Christoper Clark's hashtable implementation is very straightforward. It is more than 100 lines, but not by much.

Clark's code seems to have made its way into Google's Conccurrency Library as a parallelization example.

谷夏 2024-08-06 18:58:24

C++ 中的 std::map 本质上是一棵红黑树; 使用C 中现有的红黑树实现怎么样? 我链接的那个更像是 700 LOC,但它的评论非常好,而且从我粗略地看去,它看起来很理智。 你也许可以找到其他人; 这是“C 红黑树”在 Google 上的第一个点击。

如果您对性能不挑剔,您也可以使用不平衡二叉树或最小堆或类似的东西。 使用平衡二叉树,可以保证 O(log n) 查找; 对于不平衡的树,查找的最坏情况是 O(n) (对于节点按顺序插入的病态情况,因此最终会得到一个非常长的分支,其作用类似于链表),但是(如果我生锈了)记忆是正确的)平均情况仍然是 O(log n)。

std::map in C++ is a red-black tree under the hood; what about using an existing red-black tree implementation in C? The one I linked is more like 700 LOC, but it's pretty well commented and looks sane from the cursory glance I took at it. You can probably find others; this one was the first hit on Google for "C red-black tree".

If you're not picky about performance you could also use an unbalanced binary tree or a min-heap or something like that. With a balanced binary tree, you're guaranteed O(log n) lookup; with an unbalanced tree the worst case for lookup is O(n) (for the pathological case where nodes are inserted in-order, so you end up with one really long branch that acts like a linked-list), but (if my rusty memory is correct) the average case is still O(log n).

柠檬心 2024-08-06 18:58:22

这是一个非常简单和幼稚的

  • 固定存储桶大小
  • 无删除操作
  • 插入替换键和值,并且可以选择释放它们

#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;
}

Here's a very simple and naive one

  • Fixed bucket size
  • No delete operation
  • inserts replaces the key and value, and can optionally free them

:

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文