哈希表

实现一个简单的哈希表。

 

  1. /*
  2.  * hashtab.h -
  3.  * A hash table (hashtab) maintains associations between
  4.  * key values and datum values.  The type of the key values
  5.  * and the type of the datum values is arbitrary.  The
  6.  * functions for hash computation and key comparison are
  7.  * provided by the creator of the table.
  8.  *
  9.  * Author : jta, 2008, 6
  10.  */
  11. #ifndef _HASHTAB_H_
  12. #define _HASHTAB_H_
  13. #ifdef  __cplusplus
  14. extern "C" {
  15. #endif
  16. #define HASHTAB_MAX_NODES   0xffffffff
  17. typedef unsigned long u32;
  18. struct hashtab_node {
  19.     void *key;
  20.     void *datum;
  21.     struct hashtab_node *next;
  22. };
  23. struct hashtab {
  24.     struct hashtab_node **htable;   /* hash table */
  25.     u32 size;           /* number of slots in hash table */
  26.     u32 nel;            /* number of elements in hash table */
  27.     u32 (*hash_value)(struct hashtab *h, void *key);
  28.                     /* hash function */
  29.     int (*keycmp)(struct hashtab *h, void *key1, void *key2);
  30.                     /* key comparison function */
  31. };
  32. struct hashtab_info {
  33.     u32 slots_used;
  34.     u32 max_chain_len;
  35. };
  36. /*
  37.  * Creates a new hash table with the specified characteristics.
  38.  *
  39.  * Returns NULL if insufficent space is available or
  40.  * the new hash table otherwise.
  41.  */
  42. struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
  43.                                int (*keycmp)(struct hashtab *h, void *key1, void *key2),
  44.                                u32 size);
  45. /*
  46.  * Inserts the specified (key, datum) pair into the specified hash table.
  47.  *
  48.  * Returns -ENOMEM on memory allocation error,
  49.  * -EEXIST if there is already an entry with the same key,
  50.  * -EINVAL for general errors or
  51.  * 0 otherwise.
  52.  */
  53. #define hashtab_add hashtab_insert
  54. int hashtab_insert(struct hashtab *h, void *k, void *d);
  55. /*
  56.  * Searches for the entry with the specified key in the hash table.
  57.  *
  58.  * Returns NULL if no entry has the specified key or
  59.  * the datum of the entry otherwise.
  60.  */
  61. void *hashtab_search(struct hashtab *h, void *k);
  62. /*
  63.  * Destroys the specified hash table.
  64.  */
  65. void hashtab_destroy(struct hashtab *h);
  66. /*
  67.  * Applies the specified apply function to (key,datum,args)
  68.  * for each entry in the specified hash table.
  69.  *
  70.  * The order in which the function is applied to the entries
  71.  * is dependent upon the internal structure of the hash table.
  72.  *
  73.  * If apply returns a non-zero status, then hashtab_map will cease
  74.  * iterating through the hash table and will propagate the error
  75.  * return to its caller.
  76.  */
  77. int hashtab_map(struct hashtab *h,
  78.         int (*apply)(void *k, void *d, void *args),
  79.         void *args);
  80. /* Fill info with some hash table statistics */
  81. void hashtab_stat(struct hashtab *h, struct hashtab_info *info);
  82. #ifdef  __cplusplus
  83. }
  84. #endif
  85. #endif  /* _HASHTAB_H_ */
  1. /*
  2.  * hashtab.c - Implementation of the hash table.
  3.  *
  4.  * Author : jta, 2008, 6
  5.  */
  6. #include <string.h>
  7. #include <malloc.h>
  8. #include "hashtab.h"
  9. u32 hashfun( struct hashtab * h , void* key ) ;
  10. int keycmp(struct hashtab *h, void *key1, void *key2);
  11. struct hashtab *hashtab_create(u32 (*value)(struct hashtab *h, void *key),
  12.                                int (*cmp)(struct hashtab *h, void *key1, void *key2),
  13.                                u32 size)
  14. {
  15.     struct hashtab *p;
  16.     u32 i;
  17.     p = malloc(sizeof(*p));
  18.     if (p == NULL)
  19.         return p;
  20.     memset(p,0,sizeof(*p));
  21.     p->size = size;
  22.     p->nel = 0;
  23.     p->hash_value = value? value : hashfun;
  24.     p->keycmp = cmp ? cmp : keycmp;
  25.     p->htable = malloc(sizeof(*(p->htable)) * size);
  26.     if (p->htable == NULL) {
  27.         free(p);
  28.         return NULL;
  29.     }
  30.     for (i = 0; i < size; i++)
  31.         p->htable[i] = NULL;
  32.     return p;
  33. }
  34. int hashtab_insert(struct hashtab *h, void *key, void *datum)
  35. {
  36.     u32 hvalue;
  37.     struct hashtab_node *prev, *cur, *newnode;
  38.     if (!h || h->nel == HASHTAB_MAX_NODES)
  39.         return -1;
  40.     hvalue = h->hash_value(h, key);
  41.     prev = NULL;
  42.     cur = h->htable[hvalue];
  43.     while (cur && h->keycmp(h, key, cur->key) > 0) {
  44.         prev = cur;
  45.         cur = cur->next;
  46.     }
  47.     if (cur && (h->keycmp(h, key, cur->key) == 0))
  48.         return -1;
  49.     newnode = malloc(sizeof(*newnode));
  50.     memset(newnode, 0, sizeof(*newnode));
  51.     if (newnode == NULL)
  52.         return -1;
  53.     newnode->key = key;
  54.     newnode->datum = datum;
  55.     if (prev) {
  56.         newnode->next = prev->next;
  57.         prev->next = newnode;
  58.     } else {
  59.         newnode->next = h->htable[hvalue];
  60.         h->htable[hvalue] = newnode;
  61.     }
  62.     h->nel++;
  63.     return 0;
  64. }
  65. void *hashtab_search(struct hashtab *h, void *key)
  66. {
  67.     u32 hvalue;
  68.     struct hashtab_node *cur;
  69.     if (!h)
  70.         return NULL;
  71.     hvalue = h->hash_value(h, key);
  72.     cur = h->htable[hvalue];
  73.     while (cur != NULL && h->keycmp(h, key, cur->key) > 0)
  74.         cur = cur->next;
  75.     if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
  76.         return NULL;
  77.     return cur->datum;
  78. }
  79. void hashtab_destroy(struct hashtab *h)
  80. {
  81.     u32 i;
  82.     struct hashtab_node *cur, *temp;
  83.     if (!h)
  84.         return;
  85.     for (i = 0; i < h->size; i++) {
  86.         cur = h->htable[i];
  87.         while (cur != NULL) {
  88.             temp = cur;
  89.             cur = cur->next;
  90.             free(temp);
  91.         }
  92.         h->htable[i] = NULL;
  93.     }
  94.     free(h->htable);
  95.     h->htable = NULL;
  96.     free(h);
  97. }
  98. int hashtab_map(struct hashtab *h,
  99.         int (*apply)(void *k, void *d, void *args),
  100.         void *args)
  101. {
  102.     u32 i;
  103.     int ret;
  104.     struct hashtab_node *cur;
  105.     if (!h)
  106.         return 0;
  107.     for (i = 0; i < h->size; i++) {
  108.         cur = h->htable[i];
  109.         while (cur != NULL) {
  110.             ret = apply(cur->key, cur->datum, args);
  111.             if (ret)
  112.                 return ret;
  113.             cur = cur->next;
  114.         }
  115.     }
  116.     return 0;
  117. }
  118. void hashtab_stat(struct hashtab *h, struct hashtab_info *info)
  119. {
  120.     u32 i, chain_len, slots_used, max_chain_len;
  121.     struct hashtab_node *cur;
  122.     slots_used = 0;
  123.     max_chain_len = 0;
  124.     for (slots_used = max_chain_len = i = 0; i < h->size; i++) {
  125.         cur = h->htable[i];
  126.         if (cur) {
  127.             slots_used++;
  128.             chain_len = 0;
  129.             while (cur) {
  130.                 chain_len++;
  131.                 cur = cur->next;
  132.             }
  133.             if (chain_len > max_chain_len)
  134.                 max_chain_len = chain_len;
  135.         }
  136.     }
  137.     info->slots_used = slots_used;
  138.     info->max_chain_len = max_chain_len;
  139. }
  140. /**
  141.  * Default hash function
  142.  */
  143. u32 hashfun( struct hashtab * h , void* key )
  144. {
  145.     int* pi = (int *)key ;
  146.     return *pi%10 ;
  147. }
  148. int keycmp(struct hashtab *h, void *key1, void *key2)
  149. {
  150.     int* pi1 = (int *)key1 ;
  151.     int* pi2 = (int *)key2 ;
  152.     return *pi1 - *pi2;
  153. }
  154. #ifdef _DEBUG_HASHTAB_
  155. int main()
  156. {
  157.     struct hashtab *hash ;
  158.     u32 size = 10;
  159.     hash = hashtab_create(hashfun, keycmp, size);
  160.     int x =  (hash->hash_value)( hash, (void *)&size );
  161.     int tk = 21;
  162.     char cd[5] = "xx";
  163.     hashtab_insert(hash, (void*)&tk, (void*)cd);
  164.     char* cp = (char*)hashtab_search(hash, (void*)&tk);
  165.     printf("%s",cp);
  166.     return 0;
  167. }
  168. #endif

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值