• c语言实现带LRU机制的哈希表


      1 #include <stdint.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 
      6 #define HASH_BUCKET_MAX (1024)
      7 #define HASH_BUCKET_CAPACITY_MAX (256)
      8 #define HASHTABLE_DEBUG
      9 #define TRUE  1
     10 #define FALSE 0
     11 
     12 #ifdef HASHTABLE_DEBUG
     13 #define DEBUG(format, ...) printf("[%s] [%d] : "format"
    ", __FUNCTION__, __LINE__, __VA_ARGS__)
     14 #else
     15 #define DEBUG(format, ...)
     16 #endif
     17 
     18 struct hash_bucket {
     19     int                capacity;  /* 桶的容量 */
     20     void               *hkey;     /* hashtable的key */
     21     void               *hdata;    /* hashtable的data */
     22     struct hash_bucket *prev;
     23     struct hash_bucket *next;
     24     struct hash_bucket *tail;
     25 };
     26 
     27 struct hash {
     28     uint32_t            (*hash_key)(void *);
     29     int                 (*hash_cmp)(const void *, const void*, int len);
     30     struct hash_bucket* bucket[HASH_BUCKET_MAX];
     31 };
     32 
     33 uint32_t string_hash_key(void* str);
     34 int string_hash_cmp(const void* src, const void* dst);
     35 
     36 static struct hash *g_htable = NULL;
     37 
     38 void hash_create();
     39 void *hash_lookup(void *key);
     40 int  hash_add(void *key, void* data);
     41 int  hash_delete(void *key);
     42 void hash_destroy();
     43 void hash_iter_print();
     44 
     45 #define  bucket_free(bucket) 
     46     free(bucket->hkey);      
     47     free(bucket->hdata);     
     48     free(bucket);            
     49     bucket = NULL;
     50 
     51 uint32_t string_hash_key(void* str) {
     52     char *tmp = (char *)str;
     53     uint32_t key = 0;
     54     while(*tmp)
     55         key = (key * 33) ^ (uint32_t)(tmp++);
     56 
     57     DEBUG("string key : %u, index : %d", key, key%HASH_BUCKET_MAX);
     58 
     59     return key%HASH_BUCKET_MAX;
     60 }
     61 
     62 int string_hash_cmp(const void* src, const void* dst, int len) {
     63     if (!src || !dst) {
     64         DEBUG("src addr: %p, dst addr: %p", src, dst);
     65         return -1;
     66     }
     67     return strncmp((char *)src, (char *)dst, len);
     68 }
     69 
     70 void hash_create() {
     71     if (g_htable) {
     72         DEBUG("the default hashtable is already created");
     73         return;
     74     }
     75     
     76     g_htable = (struct hash *)malloc(sizeof(struct hash));
     77     if (!g_htable) {
     78         DEBUG("memory alloc failed.");
     79         return;
     80     }
     81 
     82     memset(g_htable, 0, sizeof(struct hash));
     83 
     84     g_htable->hash_key = string_hash_key;
     85     g_htable->hash_cmp = string_hash_cmp;
     86 
     87     return;
     88 }
     89 
     90 static void bucket_delete(struct hash_bucket** ptr) {
     91     struct hash_bucket *bucket = *ptr;
     92     struct hash_bucket *tmp;
     93 
     94     while(bucket) {
     95         tmp = bucket;
     96         bucket = bucket->next;
     97         bucket_free(tmp);
     98     }
     99 }
    100 
    101 void hash_destroy() {
    102     if (g_htable) {
    103         for(int i=0; i<HASH_BUCKET_MAX; i++) {
    104             if (g_htable->bucket[i]) {
    105                 bucket_delete(&g_htable->bucket[i]);
    106             }
    107         }
    108         
    109         free(g_htable);
    110         g_htable = NULL;
    111     }
    112     return;
    113 }
    114 
    115 #define  lru_bucket_move(bucket,  head)   
    116     bucket->next = head;                  
    117     bucket->prev = NULL;                  
    118     bucket->capacity = head->capacity;    
    119                                           
    120     head->prev = bucket;                  
    121     head->tail = NULL;    
    122 
    123 void *hash_lookup(void *key) {
    124     if (!key) {
    125         DEBUG("input para is NULL
    ");
    126         return NULL;
    127     }
    128 
    129     uint32_t index = g_htable->hash_key(key);
    130     struct hash_bucket* head = g_htable->bucket[index];
    131     struct hash_bucket* bucket = head;
    132 
    133     while(bucket) {
    134         if (0 == g_htable->hash_cmp(key, bucket->hkey, strlen((char*)key))) {
    135             if (head != bucket && bucket != head->tail) {
    136                 bucket->prev->next = bucket->next;
    137                 bucket->next->prev = bucket->prev;
    138                 bucket->tail = head->tail;
    139 
    140                 lru_bucket_move(bucket, head);
    141             } else if (bucket == head->tail && head->capacity>1) {
    142                 bucket->prev->next = NULL;
    143                 bucket->tail = bucket->prev;
    144 
    145                 lru_bucket_move(bucket, head);
    146             }
    147             g_htable->bucket[index] = bucket;
    148             return bucket->hdata;
    149         }
    150         bucket = bucket->next;
    151     }
    152     return NULL;
    153 }
    154 
    155 int hash_add(void *key, void* data) {
    156     if (!key || !data) {
    157         DEBUG("input para is NULL
    ");
    158         return FALSE;
    159     }
    160 
    161     uint32_t index = g_htable->hash_key(key);
    162     struct hash_bucket* head = g_htable->bucket[index];
    163 
    164     if (!head) {
    165         head = (struct hash_bucket*)malloc(sizeof(struct hash_bucket));
    166         if (!head) {
    167             DEBUG("no memory for more hash_bucket
    ");
    168             return FALSE;
    169         }
    170 
    171         memset(head, 0, sizeof(*head));
    172         head->capacity++;
    173         
    174         head->hkey  = strdup((char *)key);
    175         head->hdata = strdup((char *)data);        
    176         head->tail  = head;
    177         g_htable->bucket[index] = head;
    178         return TRUE;
    179     }
    180 
    181     int capacity = head->capacity;
    182     struct hash_bucket *new_bucket = 
    183         (struct hash_bucket *)malloc(sizeof(struct hash_bucket)); 
    184 
    185     if (!new_bucket) {
    186         DEBUG("no memory for more hash_bucket
    ");
    187         return FALSE;
    188     }
    189 
    190     if (capacity >= HASH_BUCKET_CAPACITY_MAX) {
    191         struct hash_bucket *tail = head->tail;
    192         head->tail = tail->prev;
    193 
    194         tail->prev->next = NULL;
    195         bucket_free(tail);
    196     } 
    197     
    198     head->prev = new_bucket;
    199     new_bucket->next = head;
    200     new_bucket->capacity = capacity + 1;
    201     new_bucket->tail = head->tail;
    202     head->tail = NULL;
    203 
    204     head->hkey  = strdup((char *)key);
    205     head->hdata = strdup((char *)data);
    206     
    207     g_htable->bucket[index] = new_bucket;
    208     
    209     return TRUE;
    210 }
    211 
    212 int hash_delete(void *key) {
    213     if (!key) {
    214         DEBUG("input para is NULL
    ");
    215         return FALSE;
    216     }
    217 
    218     uint32_t index = g_htable->hash_key(key);
    219     struct hash_bucket* head = g_htable->bucket[index];
    220     struct hash_bucket* bkt = head;
    221 
    222     while(bkt) {
    223         if (0 == g_htable->hash_cmp(key, bkt->hkey, strlen((char*)key))) {
    224             if (head != bkt && bkt != head->tail) {
    225                 bkt->prev->next = bkt->next;
    226                 bkt->next->prev = bkt->prev;
    227 
    228             } else if (bkt == head->tail && head->capacity>1) {
    229                 bkt->prev->next = NULL;
    230                 bkt->tail = bkt->prev;
    231 
    232             } else {
    233                 if (bkt->next) {
    234                     bkt->next->tail = bkt->tail;
    235                     bkt->next->capacity = bkt->capacity;
    236                     bkt->next->prev = NULL;
    237                     g_htable->bucket[index] = bkt->next;
    238                 } else {
    239                     g_htable->bucket[index] = NULL;
    240                 }
    241             }
    242 
    243             bucket_free(bkt);
    244             if (g_htable->bucket[index]) {
    245                 g_htable->bucket[index]->capacity--;
    246             }
    247             
    248             return TRUE;
    249         }
    250         bkt = bkt->next;
    251     }
    252     return FALSE;
    253 }
    254 
    255 static void bucket_print(struct hash_bucket** ptr) {
    256     struct hash_bucket *bkt = *ptr;
    257     struct hash_bucket *tmp;
    258 
    259     while(bkt) {
    260         printf("key=[%s],data=[%s]
    ", (char*)bkt->hkey, (char*)bkt->hdata);
    261         bkt = bkt->next;
    262     }
    263 }
    264 
    265 void hash_iter_print() {
    266     if (g_htable) {
    267         for(int i=0; i<HASH_BUCKET_MAX; i++) {
    268             if (g_htable->bucket[i]) {
    269                 bucket_print(&g_htable->bucket[i]);
    270             }
    271         }
    272     }
    273 }
    274 
    275 int main(int argc, char* argv[]) {
    276     hash_create();
    277 
    278     hash_add("first", "danxi");
    279     hash_add("second", "test");
    280     hash_add("three", "sad code");
    281     hash_add("four", "let's go");
    282 
    283     hash_iter_print();
    284 
    285     char * t1 = (char *)hash_lookup("first");
    286     char * t2 = (char *)hash_lookup("second");
    287 
    288     printf("%s  %s 
    ", t1, t2);
    289     printf("%s 
    ", (char*)hash_lookup("four"));
    290 
    291     hash_delete("four");
    292     hash_iter_print();
    293     hash_destroy();
    294 
    295     return 0;
    296 }
  • 相关阅读:
    js数组去重
    js和jq实现全选反选
    js的作用域深入理解
    js对数组的常用操作
    如何写出让java虚拟机发生内存溢出异常OutOfMemoryError的代码
    JAVA编程思想(第四版)学习笔记----4.8 switch(知识点已更新)
    通过拦截器Interceptor实现Spring MVC中Controller接口访问信息的记录
    JAVA编程思想(第四版)学习笔记----11.10 Map
    JAVA中的for-each循环与迭代
    JAVA编程思想(第四版)学习笔记----11.5 List,11.6迭代器
  • 原文地址:https://www.cnblogs.com/danxi/p/6727142.html
Copyright © 2020-2023  润新知