2009-08-05 18 views
7

Tôi có một chương trình đọc url trong một tệp và thực hiện gethostbyname() trên mỗi máy chủ URL. Cuộc gọi này khá tốn kém. Tôi muốn lưu chúng.Cài đặt bản đồ rất đơn giản trong C (cho mục đích bộ nhớ đệm)?

Có đoạn mã bản đồ cơ sở rất đơn giản trong C ở đó mà tôi có thể sử dụng để thực hiện bộ nhớ đệm không? (Tôi chỉ không muốn phát minh lại bánh xe).

Nó phải có những điểm sau đây:

  • nguồn mở với một dễ dãi giấy phép (nghĩ BSD hoặc phạm vi công cộng).
  • Rất đơn giản: lý tưởng ít hơn 100 LỘC
  • Keys là char* và đánh giá cao void*. Không cần phải sao chép chúng.
  • Không cần thực hiện remove(), nhưng cần hoặc put() thay thế giá trị.

PS: Tôi đã gắn thẻ nó bài tập về nhà, vì có thể. Tôi chỉ là rất lười biếng và muốn tránh tất cả những cạm bẫy phổ biến mà tôi có thể gặp phải trong khi thực hiện lại.

+0

@Sinan & Meredith: Tôi chấp nhận mã snipped vì nó là ** chính xác ** những gì tôi đang tìm kiếm. –

Trả lời

5

Dưới đây là một rất đơn giản và ngây thơ một

  • kích thước cố định xô
  • Không hoạt động xóa
  • chèn thay thế chìa khóa và giá trị, và tùy chọn có thể giải phóng chúng

:

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

+1: Chính xác những gì tôi đang tìm kiếm. Tôi chỉnh sửa mã một chút để đối phó với chính xác const-ness (key & value). Bây giờ ứng dụng của tôi bắt đầu trong chưa đầy một giây, thay vì 2 phút @ 100% cpu :-) –

1

memcached?

Không phải đoạn mã, mà là công cụ lưu vào bộ nhớ cache được phân phối hiệu suất cao.

+0

-1: Tôi muốn tránh một syscall ('gethostbyname()'), vì vậy tôi không thực sự nghĩ rằng memcached phù hợp với các hóa đơn ở đây. –

1

Không lười biếng, nhạy cảm sâu để tránh viết nội dung này.

Làm thế nào điều này library không bao giờ sử dụng nó bản thân mình nhưng nó dường như yêu cầu bồi thường để làm những gì bạn yêu cầu.

+0

Thư viện có vẻ thú vị, nhưng bản cập nhật cuối cùng cho trang web là năm 2005. Sẽ tốt cho một vài dòng mã, nhưng hơi quá cũ đối với một thư viện đầy đủ. –

+0

Vâng, các thuật toán cơ bản được triển khai tốt sẽ không trở thành ngày tháng. Tôi sẽ không quan tâm đến việc sử dụng thư viện 4 năm thuộc loại này - giả sử rằng họ thực sự đã làm việc ngay từ đầu. Nếu bạn ahve mã, sau đó bảo trì không nên quá nhiều của một vấn đề. – djna

5

Christoper Clark's hashtable implementation rất đơn giản. Nó có hơn 100 dòng, nhưng không nhiều.

Mã của Clark dường như đã thực hiện theo cách của mình vào Google's Conccurrency Library làm ví dụ song song.

+0

+1: Có vẻ như để trả lời câu hỏi, tôi sẽ xem xét nó. –

+0

Liên kết trong câu trả lời chỉ liên kết này đã chết. – vaultah

+1

@vaultah Chỉ liên kết đến 'archive.org'. Cảm ơn cho những người đứng đầu lên. –

3

std::map trong C++ là một cây đỏ đen dưới mui xe; những gì về việc sử dụng an existing red-black tree implementation in C? Cái tôi liên kết giống như 700 LOC, nhưng nó được đánh giá khá tốt và trông có vẻ lành mạnh từ cái nhìn lướt qua mà tôi lấy nó. Bạn có thể tìm thấy người khác; đây là lần truy cập đầu tiên trên Google cho "C-cây đỏ đen".

Nếu bạn không cầu kỳ về hiệu suất, bạn cũng có thể sử dụng cây nhị phân không cân bằng hoặc min-heap hoặc thứ gì đó tương tự. Với cây nhị phân cân bằng, bạn được đảm bảo tra cứu O (log n); với cây không cân bằng, trường hợp xấu nhất để tra cứu là O (n) (cho trường hợp bệnh lý nơi các nút được chèn vào theo thứ tự, vì vậy bạn kết thúc với một nhánh dài thực sự hoạt động như một danh sách liên kết), nhưng (nếu tôi bị gỉ bộ nhớ là chính xác) trường hợp trung bình vẫn là O (log n).

+0

+1: Có vẻ như để trả lời câu hỏi, tôi sẽ xem xét nó. –

0

Tìm thấy triển khai tại đây: c tệp và h tệp khá gần với những gì bạn đã hỏi.W3C giấy phép

1

C Interfaces and Implementations của Dave Hanson bao gồm một bảng băm đẹp, cũng như nhiều mô-đun hữu ích khác. Bảng băm đồng hồ ở 150 dòng, nhưng bao gồm quản lý bộ nhớ, hàm ánh xạ bậc cao và chuyển đổi thành mảng. Phần mềm này miễn phí và cuốn sách đáng mua.

2

Bạn có thể thử sử dụng sau implemntation

clib

+0

+1: dự án của bạn có vẻ khá thú vị, thx. –

+0

Cảm ơn, Nó vẫn đang hoạt động. Hy vọng sẽ kết thúc sau 2 tuần nữa. – Avinash