免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 7250 | 回复: 24
打印 上一主题 下一主题

写了个哈希表,欢迎批评指正...(经强力测试, 伤得起) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-10-29 12:02 |只看该作者 |倒序浏览
本帖最后由 三月廿七 于 2011-10-30 09:06 编辑
  1. #ifndef HASHTABLE_H_
  2. #define HASHTABLE_H_

  3. typedef struct xHashTable* HashTable;

  4. /*
  5. * 哈希函数
  6. */
  7. typedef unsigned int (*hashFunction)(const void* key, int capacity);

  8. /*
  9. * 比较函数
  10. */
  11. typedef int (*compareFunction)(const void* a, const void* b);

  12. /*
  13. * 显示函数
  14. */
  15. typedef void (*showFunction)(const void* key, const void* item);

  16. /*
  17. * 键复制函数
  18. */
  19. typedef void*(*keyCloneFunction)(void* key);

  20. /*
  21. * 项复制函数
  22. */
  23. typedef void*(*itemCloneFunction)(void* item);

  24. /*
  25. * 键释放函数
  26. */
  27. typedef void (*keyDeleteFunction)(void* key);

  28. /*
  29. * 项释放函数
  30. */
  31. typedef void (*itemDeleteFunction)(void* item);

  32. /*
  33. * 构造哈希表
  34. */
  35. HashTable HASHTABLEnew(int max, int number, hashFunction hash,
  36.                        compareFunction compare, showFunction show,
  37.                        keyCloneFunction keyClone, itemCloneFunction itemClone,
  38.                        keyDeleteFunction keyDelete, itemDeleteFunction itemDelete);

  39. /**
  40. * 释放哈希表
  41. */
  42. void HASHTABLEdelete(HashTable hashTable);

  43. /**
  44. * 添加项
  45. */
  46. int HASHTABLEinsert(HashTable hashTable, void* key, void* item);

  47. /**
  48. * 查找项
  49. */
  50. void* HASHTABLEsearch(HashTable hashTable, void* key);

  51. /**
  52. * 删除项
  53. */
  54. int HASHTABLEremove(HashTable hashTable, void* key);

  55. /**
  56. * 重设哈希表大小
  57. */
  58. int HASHTABLEresize(HashTable hashTable, int size);

  59. /**
  60. * 遍历哈希表
  61. */
  62. void HASHTABLEtraverse(HashTable hashTable);

  63. #endif
复制代码
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4. #include "HashTable.h"

  5. #define TRUE 1

  6. #define FALSE 0

  7. typedef struct xHashTableNode HASHTABLEnode;

  8. typedef HASHTABLEnode* HashTableNode;

  9. struct xHashTableNode
  10. {
  11.     void* key;
  12.     void* item;
  13.     HashTableNode next;
  14. } ;

  15. typedef struct xHashTableChain HASHTABLEchain;

  16. typedef HASHTABLEchain* HashTableChain;

  17. struct xHashTableChain
  18. {
  19.     // 分离链中的第一个链接
  20.     HashTableNode head;

  21.     // 分离链的长度
  22.     int size;
  23. } ;

  24. typedef struct xHashTable HASHTABLE;

  25. struct xHashTable
  26. {
  27.     // 分离链表
  28.     HashTableChain* table;

  29.     // 项的最大个数
  30.     int max;

  31.     // 平均每个链中的项的个数
  32.     int number;

  33.     // 项的个数
  34.     int size;

  35.     // 分离链个数
  36.     int capacity;

  37.     hashFunction hash;
  38.     compareFunction compare;
  39.     showFunction show;
  40.     keyCloneFunction keyClone;
  41.     itemCloneFunction itemClone;
  42.     keyDeleteFunction keyDelete;
  43.     itemDeleteFunction itemDelete;
  44. };

  45. static HashTableNode HASHTABLENODEnew(void* key, void* item, HashTableNode next)
  46. {
  47.     HashTableNode node = malloc(sizeof * node);

  48.     if (node == NULL)
  49.     {
  50.         return NULL;
  51.     }

  52.     node->key = key;
  53.     node->item = item;
  54.     node->next = next;
  55.     return node;
  56. }

  57. static HashTableChain HASHTABLECHAINnew(void)
  58. {
  59.     HashTableChain chain = malloc(sizeof * chain);

  60.     if (chain == NULL)
  61.     {
  62.         return NULL;
  63.     }

  64.     chain->head = NULL;
  65.     chain->size = 0;
  66.     return chain;
  67. }

  68. HashTable HASHTABLEnew(int max, int number, hashFunction hash,
  69.                        compareFunction compare, showFunction show,
  70.                        keyCloneFunction keyClone, itemCloneFunction itemClone,
  71.                        keyDeleteFunction keyDelete, itemDeleteFunction itemDelete)
  72. {
  73.     HashTable hashTable = malloc(sizeof * hashTable);
  74.     int i, c;

  75.     if (hashTable == NULL)
  76.     {
  77.         return NULL;
  78.     }

  79.     c = max / number;
  80.     hashTable->table = malloc(c * sizeof * hashTable->table);

  81.     if (hashTable->table == NULL)
  82.     {
  83.         free(hashTable);
  84.         return NULL;
  85.     }

  86.     for (i = 0; i < c; i++)
  87.     {
  88.         hashTable->table[i] = NULL;
  89.     }

  90.     hashTable->max = max;
  91.     hashTable->number = number;
  92.     hashTable->size = 0;
  93.     hashTable->capacity = c;
  94.     hashTable->show = show;
  95.     hashTable->hash = hash;
  96.     hashTable->compare = compare;
  97.     hashTable->keyClone = keyClone;
  98.     hashTable->itemClone = itemClone;
  99.     hashTable->keyDelete = keyDelete;
  100.     hashTable->itemDelete = itemDelete;
  101.     return hashTable;
  102. }

  103. void HASHTABLEdelete(HashTable hashTable)
  104. {
  105.     int i;
  106.     assert(hashTable);

  107.     for (i = 0; i < hashTable->capacity; i++)
  108.     {
  109.         HashTableNode save, it;

  110.         if (hashTable->table[i] == NULL)
  111.         {
  112.             continue;
  113.         }

  114.         it = hashTable->table[i]->head;

  115.         for (; it != NULL; it = save)
  116.         {
  117.             save = it->next;
  118.             hashTable->keyDelete(it->key);
  119.             hashTable->itemDelete(it->item);
  120.             free(it);
  121.         }

  122.         free(hashTable->table[i]);
  123.     }

  124.     free(hashTable->table);
  125.     free(hashTable);
  126. }

  127. void* HASHTABLEsearch(HashTable hashTable, void* key)
  128. {
  129.     unsigned int h;
  130.     assert(hashTable);
  131.     h = hashTable->hash(key, hashTable->capacity);

  132.     if (hashTable->table[h] != NULL)
  133.     {
  134.         HashTableNode it = hashTable->table[h]->head;

  135.         for (; it != NULL; it = it->next)
  136.         {
  137.             if (hashTable->compare(key, it->key) == 0)
  138.             {
  139.                 return it->item;
  140.             }
  141.         }
  142.     }

  143.     return NULL;
  144. }

  145. int HASHTABLEinsert(HashTable hashTable, void* key, void* item)
  146. {
  147.     unsigned int h;
  148.     void* tempKey, *tempItem;
  149.     HashTableNode tempNode;
  150.     assert(hashTable);
  151.     h = hashTable->hash(key, hashTable->capacity);

  152.     // 不允许重复项
  153.     if (HASHTABLEsearch(hashTable, key) != NULL)
  154.     {
  155.         return FALSE;
  156.     }

  157.     tempKey = hashTable->keyClone(key);
  158.     tempItem = hashTable->itemClone(item);
  159.     tempNode = HASHTABLENODEnew(tempKey, tempItem, NULL);

  160.     if (tempNode == NULL)
  161.     {
  162.         return FALSE;
  163.     }

  164.     if (hashTable->table[h] == NULL)
  165.     {
  166.         hashTable->table[h] = HASHTABLECHAINnew();

  167.         if (hashTable->table[h] == NULL)
  168.         {
  169.             hashTable->keyDelete(tempNode->key);
  170.             hashTable->itemDelete(tempNode->item);
  171.             free(tempNode);
  172.             return FALSE;
  173.         }
  174.     }

  175.     tempNode->next = hashTable->table[h]->head;
  176.     hashTable->table[h]->head = tempNode;
  177.     hashTable->table[h]->size++;
  178.     hashTable->size++;

  179.     if (hashTable->size > hashTable->max / 2)
  180.     {
  181.         if (!HASHTABLEresize(hashTable, hashTable->max * 2))
  182.         {
  183.             return FALSE;
  184.         }
  185.     }

  186.     return TRUE;
  187. }

  188. int HASHTABLEremove(HashTable hashTable, void* key)
  189. {
  190.     unsigned int h;
  191.     HashTableNode save, it;
  192.     assert(hashTable);
  193.     h = hashTable->hash(key, hashTable->capacity);

  194.     if (hashTable->table[h] == NULL)
  195.     {
  196.         return FALSE;
  197.     }

  198.     it = hashTable->table[h]->head;

  199.     if (hashTable->compare(key, it->key) == 0)
  200.     {
  201.         hashTable->table[h]->head = it->next;
  202.         hashTable->keyDelete(it->key);
  203.         hashTable->itemDelete(it->item);
  204.         free(it);

  205.         if (hashTable->table[h]->head == NULL)
  206.         {
  207.             free(hashTable->table[h]);
  208.             hashTable->table[h] = NULL;
  209.         }
  210.         else
  211.         {
  212.             hashTable->table[h]->size--;
  213.         }
  214.     }
  215.     else
  216.     {
  217.         while (it->next != NULL)
  218.         {
  219.             if (hashTable->compare(key, it->next->key) == 0)
  220.             {
  221.                 break;
  222.             }

  223.             it = it->next;
  224.         }

  225.         if (it->next == NULL)
  226.         {
  227.             return FALSE;
  228.         }

  229.         save = it->next;
  230.         it->next = it->next->next;
  231.         hashTable->keyDelete(save->key);
  232.         hashTable->itemDelete(save->item);
  233.         free(save);
  234.         hashTable->table[h]->size--;
  235.     }

  236.     hashTable->size--;
  237.     return TRUE;
  238. }

  239. static TABLEfree(HashTable hashTable)
  240. {
  241.         HashTableNode it, save;
  242.         int i;

  243.         for (i = 0; i < hashTable->capacity; i++)
  244.         {
  245.                 if (hashTable->table[i] == NULL)
  246.                 {
  247.                         continue;
  248.                 }

  249.                 it = hashTable->table[i]->head;

  250.                 for (; it != NULL; it = save)
  251.                 {
  252.                         save = it->next;
  253.                         hashTable->keyDelete(it->key);
  254.                         hashTable->itemDelete(it->item);
  255.                         free(it);
  256.                 }

  257.                 free(hashTable->table[i]);
  258.         }

  259.         free(hashTable->table);
  260. }

  261. int HASHTABLEresize(HashTable hashTable, int size)
  262. {
  263.         HashTableChain* table;
  264.         HashTableNode it;
  265.         void* tempKey, *tempItem;
  266.         HashTableNode tempNode;
  267.         int i, c;
  268.         unsigned int h;
  269.        
  270.         c = size / hashTable->number;
  271.         table = malloc(c * sizeof * table);

  272.         if (table == NULL)
  273.         {
  274.                 return FALSE;
  275.         }

  276.         for (i = 0; i < c; i++)
  277.         {
  278.                 table[i] = NULL;
  279.         }

  280.         for (i = 0; i < hashTable->capacity; i++)
  281.         {
  282.                 if (hashTable->table[i] == NULL)
  283.                 {
  284.                         continue;
  285.                 }

  286.                 for (it = hashTable->table[i]->head; it != NULL; it = it->next)
  287.                 {
  288.                         h = hashTable->hash(it->key, c);

  289.                         if (table[h] == NULL)
  290.                         {
  291.                                 table[h] = HASHTABLECHAINnew();

  292.                                 if (table[h] == NULL)
  293.                                 {
  294.                                         return FALSE;
  295.                                 }
  296.                         }

  297.                         tempKey = hashTable->keyClone(it->key);
  298.                         tempItem = hashTable->itemClone(it->item);
  299.                         tempNode = HASHTABLENODEnew(tempKey, tempItem, NULL);

  300.                         tempNode->next = table[h]->head;
  301.                         table[h]->head = tempNode;
  302.                         table[h]->size++;
  303.                 }
  304.         }

  305.         TABLEfree(hashTable);

  306.         hashTable->table = table;
  307.         hashTable->max = size;
  308.         hashTable->capacity = c;
  309.         return TRUE;
  310. }

  311. void HASHTABLEtraverse(HashTable hashTable)
  312. {
  313.     int i;
  314.     assert(hashTable);

  315.     for (i = 0; i < hashTable->capacity; i++)
  316.     {
  317.         HashTableNode it;

  318.         if (hashTable->table[i] == NULL)
  319.         {
  320.             continue;
  321.         }

  322.         it = hashTable->table[i]->head;

  323.         for (; it != NULL; it = it->next)
  324.         {
  325.             hashTable->show(it->key, it->item);
  326.         }

  327.         printf("\n");
  328.     }
  329. }
复制代码
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include "HashTable.h"

  5. unsigned int STRINGhash(const void* key, int capacity);

  6. int STRINGcompare(const void* a, const void* b);

  7. void STRINGshow(const void* key, const void* item);

  8. void* STRINGkeyClone(void* key);

  9. void* STRINGitemClone(void* item);

  10. void STRINGkeyDelete(void* key);

  11. void STRINGitemDelete(void* item);

  12. int main(void)
  13. {
  14.     HashTable hashTable = HASHTABLEnew(10, 5, STRINGhash,
  15.                                        STRINGcompare, STRINGshow,
  16.                                        STRINGkeyClone, STRINGitemClone,
  17.                                        STRINGkeyDelete, STRINGitemDelete);
  18.     HASHTABLEinsert(hashTable, "BlueGuy0", "920170678");
  19.     HASHTABLEinsert(hashTable, "BlueGuy1", "920170678");
  20.     HASHTABLEinsert(hashTable, "BlueGuy2", "920170678");
  21.     HASHTABLEinsert(hashTable, "BlueGuy3", "920170678");
  22.     HASHTABLEinsert(hashTable, "BlueGuy4", "920170678");
  23.     HASHTABLEinsert(hashTable, "BlueGuy5", "920170678");
  24.     HASHTABLEinsert(hashTable, "BlueGuy6", "920170678");
  25.     HASHTABLEinsert(hashTable, "BlueGuy7", "920170678");
  26.     HASHTABLEinsert(hashTable, "BlueGuy8", "920170678");
  27.     HASHTABLEinsert(hashTable, "BlueGuy9", "920170678");
  28.     HASHTABLEinsert(hashTable, "BlueGuy ", "920170678");
  29.     HASHTABLEtraverse(hashTable);
  30.     HASHTABLEdelete(hashTable);
  31.     getchar();
  32.     return 0;
  33. }

  34. unsigned int STRINGhash(const void* key, int capacity)
  35. {
  36.     unsigned int h = 0, a = 255;
  37.     unsigned char* str = (unsigned char*)key;

  38.     for (; *str ; str++)
  39.     {
  40.         h = (a * h + *str) % capacity;
  41.     }

  42.     return h;
  43. }

  44. int STRINGcompare(const void* a, const void* b)
  45. {
  46.     const char* a1 = (const char*) a;
  47.     const char* a2 = (const char*) b;
  48.     return strcmp(a1, a2);
  49. }

  50. void STRINGshow(const void* key, const void* item)
  51. {
  52.     const char* a1 = (const char*) key;
  53.     const char* a2 = (const char*) item;
  54.     printf("%s: %s\n", a1, a2);
  55. }

  56. void* STRINGkeyClone(void* key)
  57. {
  58.     return key;
  59. }

  60. void* STRINGitemClone(void* item)
  61. {
  62.     return item;
  63. }

  64. void STRINGkeyDelete(void* key)
  65. {
  66. }

  67. void STRINGitemDelete(void* item)
  68. {
  69. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2011-10-29 12:28 |只看该作者
牛逼,随便就写了个哈希表。

论坛徽章:
0
3 [报告]
发表于 2011-10-29 12:29 |只看该作者
本帖最后由 三月廿七 于 2011-10-29 12:34 编辑
牛逼,随便就写了个哈希表。
huxk 发表于 2011-10-29 12:28

是吹的,

论坛徽章:
0
4 [报告]
发表于 2011-10-29 12:34 |只看该作者
回复 3# 三月廿七


    这种东东再配个内存管理 比如 内存池就更好了。

论坛徽章:
5
技术图书徽章
日期:2013-11-07 13:21:58技术图书徽章
日期:2013-12-07 10:34:46技术图书徽章
日期:2014-04-23 08:50:31双鱼座
日期:2014-09-16 09:12:34亥猪
日期:2015-01-23 13:37:49
5 [报告]
发表于 2011-10-29 13:28 |只看该作者
膜拜,哈希表是啥?这玩意又啥用?

论坛徽章:
2
技术图书徽章
日期:2013-09-04 15:21:51酉鸡
日期:2013-11-01 21:20:20
6 [报告]
发表于 2011-10-29 13:35 |只看该作者
现在好多系统都带哈希API了,构建一个hash算法,直接用就行了。干嘛总是要自己写呢?

论坛徽章:
0
7 [报告]
发表于 2011-10-29 14:13 |只看该作者
膜拜,哈希表是啥?这玩意又啥用?
nketc 发表于 2011-10-29 13:28

本来是想让你指点的, 结果被膜拜了, {:3_183:}

论坛徽章:
0
8 [报告]
发表于 2011-10-29 14:36 |只看该作者
本帖最后由 三月廿七 于 2011-10-29 14:43 编辑
现在好多系统都带哈希API了,构建一个hash算法,直接用就行了。干嘛总是要自己写呢?
mirnshi 发表于 2011-10-29 13:35

代码 和 代码能力 是 积累出来的,没事写几行代码练练动手能力...
说不定哪一天这段代码就会用的上, 也说不定哪一天代码能力会发生质变,
然后由众人鄙视的对象跃升为众人膜拜的偶像...

论坛徽章:
0
9 [报告]
发表于 2011-10-29 15:47 |只看该作者
莫拜

论坛徽章:
0
10 [报告]
发表于 2011-10-29 18:06 |只看该作者
哈希函数,我就记得DEK的了,这个好记就是在于没有magic number

  1. unsigned int DEKHash(char* str, unsigned int len)
  2. {
  3.         unsigned int hash = len;
  4.         char* str_end = str+len;

  5.         for( ; str < str_end; str++)
  6.         {
  7.                 hash = ((hash << 5) ^ (hash >> 27)) ^ (*str);
  8.         }
  9.         return hash;
  10. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP