c语言实现通用数据结构(五):通用映射(HashMap)

转载:http://blog.csdn.net/swwlqw/article/details/22666705

这是在通用链表的基础上实现的映射,关于链表的实现参见:http://blog.csdn.net/swwlqw/article/details/22498833

注意映射中只存储了key和value的指针,没有储存实际的数据。

对于新的key类型来说,需要自定义HashCode函数和equal函数。

在HashSet的实现中给出了几个常见的hashCode函数和equal函数。参见:http://blog.csdn.net/swwlqw/article/details/22664129


头文件:myHashMap.h

[cpp]  view plain  copy
  1. #ifndef MYHASHMAP_H_INCLUDED  
  2. #define MYHASHMAP_H_INCLUDED  
  3. #include "myList.h"  
  4.   
  5. #define DEFAULT_INITIAL_CAPACITY 16  
  6. #define DEFAULT_LOAD_FACTOR 0.75f  
  7.   
  8. typedef struct entry  
  9. {  
  10.     void * key;  
  11.     void * value;  
  12. } Entry;  
  13.   
  14. typedef struct myHashMap  
  15. {  
  16.     int size;   //大小  
  17.     int initialCapacity; //初始容量  
  18.     float loadFactor;   //加载因子  
  19.     int (*hashCode)(void *key);  
  20.     int (*equal)(void *key1,void *key2);  
  21.     MyList ** entryList;  
  22. } MyHashMap;  
  23.   
  24. typedef struct myHashMapEntryIterator  
  25. {  
  26.     int index;       //第几个链表  
  27.     MyHashMap *map;  
  28.     MyNode *current;  
  29.     int count;        //第几个数据  
  30. } MyHashMapEntryIterator;  
  31.   
  32. //创建HashMap  
  33. MyHashMap *createMyHashMap(int (*hashCode)(void *key),int (*equal)(void *key1,void *key2));  
  34.   
  35. //使用全部参数创建HashMap  
  36. MyHashMap *createMyHashMapForAll(int initialCapacity,float loadFactor,int (*hashCode)(void *key),int (*equal)(void *key1,void *key2));  
  37.   
  38. //释放HashMap  
  39. void freeMyHashMap(MyHashMap * map);  
  40.   
  41. //是否包含某个key  
  42. int myHashMapContainsKey(MyHashMap *const map,void * const key);  
  43.   
  44. //增加一条映射  
  45. void myHashMapPutData(MyHashMap *const map,void * const key,void * const value);  
  46.   
  47. //通过key得到数据,如果没有数据则返回null  
  48. void* myHashMapGetDataByKey(MyHashMap * const map,void *const key);  
  49.   
  50. //数据的容量  
  51. int myHashMapGetSize(const MyHashMap * const map);  
  52.   
  53. //创建Entry迭代器  
  54. MyHashMapEntryIterator* createMyHashMapEntryIterator( MyHashMap *const map);  
  55.   
  56. //释放Entry迭代器  
  57. void freeMyHashMapEntryIterator(MyHashMapEntryIterator* iterator);  
  58.   
  59. //Entry迭代器是否有下一个  
  60. int myHashMapEntryIteratorHasNext(MyHashMapEntryIterator* iterator);  
  61.   
  62. //遍历下一个Entry元素  
  63. Entry* myHashMapEntryIteratorNext(MyHashMapEntryIterator* iterator);  
  64.   
  65. //删除一条数据,返回是否删除成功  
  66. int myHashMapRemoveDataByKey(MyHashMap *const map,void * const key);  
  67.   
  68. //遍历  
  69. void myHashMapOutput(MyHashMap *map, void(*pt)(Entry*));  
  70.   
  71. #endif // MYHASHMAP_H_INCLUDED  

源文件:  myHashMap.c

[cpp]  view plain  copy
  1. #include "myHashMap.h"  
  2. #include <stdlib.h>  
  3.   
  4. //某条Entry链表上是否包含某个key值。  
  5. Entry* listContainsEntry(MyList * list, void * key,  
  6.         int(*equal)(void *key1, void *key2)) {  
  7.     MyListIterator* it = createMyListIterator(list);  
  8.     while (myListIteratorHasNext(it)) {  
  9.         Entry * entry = (Entry *) (myListIteratorNext(it));  
  10.         if (entry->key == key || (equal != NULL && (*equal)(entry->key, key))) {  
  11.             return entry;  
  12.         }  
  13.     }  
  14.     freeMyListIterator(it);  
  15.     return NULL;  
  16. }  
  17.   
  18. void rebuildMyHashMap(MyHashMap * map) {  
  19.     int newSize = map->initialCapacity * 2;  
  20.     MyList **newentryList = (MyList **) malloc(sizeof(MyList*) * newSize);  
  21.     for (int i = 0; i < newSize; i++) {  
  22.         newentryList[i] = createMyList();  
  23.     }  
  24.     MyHashMapEntryIterator* it = createMyHashMapEntryIterator(map);  
  25.     while (myHashMapEntryIteratorHasNext(it)) {  
  26.         Entry * entry = myHashMapEntryIteratorNext(it);  
  27.         int hasCode = (*(map->hashCode))(entry->key);  
  28.         hasCode %= newSize;  
  29.         if (hasCode < 0)  
  30.             hasCode += newSize;  
  31.         myListInsertDataAtLast(newentryList[hasCode], entry);  
  32.     }  
  33.     freeMyHashMapEntryIterator(it);  
  34.     for (int i = 0; i < map->initialCapacity; i++) {  
  35.         freeMyList(map->entryList[i]);  
  36.     }  
  37.     free(map->entryList);  
  38.     map->entryList = newentryList;  
  39.     map->initialCapacity = newSize;  
  40. }  
  41.   
  42. //创建HashMap  
  43. MyHashMap *createMyHashMap(int(*hashCode)(void *key),  
  44.         int(*equal)(void *key1, void *key2)) {  
  45.     MyHashMap *re = (MyHashMap *) malloc(sizeof(MyHashMap));  
  46.     re->size = 0;  
  47.     re->loadFactor = DEFAULT_LOAD_FACTOR;  
  48.     re->initialCapacity = DEFAULT_INITIAL_CAPACITY;  
  49.     re->entryList = (MyList **) malloc(sizeof(MyList*) * re->initialCapacity);  
  50.     re->hashCode = hashCode;  
  51.     re->equal = equal;  
  52.     for (int i = 0; i < re->initialCapacity; i++) {  
  53.         re->entryList[i] = createMyList();  
  54.     }  
  55.     return re;  
  56. }  
  57.   
  58. //使用全部参数创建HashMap  
  59. MyHashMap *createMyHashMapForAll(int initialCapacity, float loadFactor,  
  60.         int(*hashCode)(void *key), int(*equal)(void *key1, void *key2)) {  
  61.     MyHashMap *re = createMyHashMap(hashCode, equal);  
  62.     re->initialCapacity = initialCapacity;  
  63.     re->loadFactor = loadFactor;  
  64.     return re;  
  65. }  
  66.   
  67. //是否包含某个key  
  68. int myHashMapContainsKey(MyHashMap * const map, void * const key) {  
  69.     int hasCode = (*(map->hashCode))(key);  
  70.     hasCode %= map->initialCapacity;  
  71.     if (hasCode < 0)  
  72.         hasCode += map->initialCapacity;  
  73.     Entry * re = listContainsEntry(map->entryList[hasCode], key, map->equal);  
  74.     return re != NULL;  
  75. }  
  76.   
  77. //增加一条映射  
  78. void myHashMapPutData(MyHashMap * const map, void * const key,  
  79.         void * const value) {  
  80.     int hasCode = (*(map->hashCode))(key);  
  81.     hasCode %= map->initialCapacity;  
  82.     if (hasCode < 0)  
  83.         hasCode += map->initialCapacity;  
  84.     Entry * re = listContainsEntry(map->entryList[hasCode], key, map->equal);  
  85.     if (re == NULL) {  
  86.         Entry * entry = (Entry*) malloc(sizeof(Entry));  
  87.         entry->key = key;  
  88.         entry->value = value;  
  89.         myListInsertDataAtLast(map->entryList[hasCode], entry);  
  90.         (map->size)++;  
  91.         if (map->size > map->initialCapacity * map->loadFactor) {  
  92.             rebuildMyHashMap(map);  
  93.         }  
  94.     } else {  
  95.         re->value = value;  
  96.     }  
  97. }  
  98.   
  99. //通过key得到数据,如果没有数据则返回null  
  100. void* myHashMapGetDataByKey(MyHashMap * const map, void * const key) {  
  101.     int hasCode = (*(map->hashCode))(key);  
  102.     hasCode %= map->initialCapacity;  
  103.     if (hasCode < 0)  
  104.         hasCode += map->initialCapacity;  
  105.     Entry * re = listContainsEntry(map->entryList[hasCode], key, map->equal);  
  106.     if (re == NULL) {  
  107.         return NULL;  
  108.     }  
  109.     return re->value;  
  110. }  
  111.   
  112. //数据的容量  
  113. int myHashMapGetSize(const MyHashMap * const map) {  
  114.     return map->size;  
  115. }  
  116.   
  117. //创建Entry迭代器  
  118. MyHashMapEntryIterator* createMyHashMapEntryIterator(MyHashMap * const map) {  
  119.     MyHashMapEntryIterator* re = (MyHashMapEntryIterator*) malloc(  
  120.             sizeof(MyHashMapEntryIterator));  
  121.     re->count = 0;  
  122.     re->index = 0;  
  123.     re->map = map;  
  124.     re->current = map->entryList[0]->first;  
  125.     return re;  
  126. }  
  127.   
  128. //释放Entry迭代器  
  129. void freeMyHashMapEntryIterator(MyHashMapEntryIterator* iterator) {  
  130.     free(iterator);  
  131. }  
  132.   
  133. //Entry迭代器是否有下一个  
  134. int myHashMapEntryIteratorHasNext(MyHashMapEntryIterator* iterator) {  
  135.     return iterator->count < iterator->map->size;  
  136. }  
  137.   
  138. //遍历下一个Entry元素  
  139. Entry* myHashMapEntryIteratorNext(MyHashMapEntryIterator* iterator) {  
  140.     (iterator->count)++;  
  141.     while (!(iterator->current)) {  
  142.         (iterator->index)++;  
  143.         iterator->current = iterator->map->entryList[iterator->index]->first;  
  144.     }  
  145.     Entry * re = (Entry *) iterator->current->data;  
  146.     iterator->current = iterator->current->next;  
  147.     return re;  
  148. }  
  149.   
  150. //删除一条数据,返回是否删除成功  
  151. int myHashMapRemoveDataByKey(MyHashMap * const map, void * const key) {  
  152.     int hasCode = (*(map->hashCode))(key);  
  153.     hasCode %= map->initialCapacity;  
  154.     if (hasCode < 0)  
  155.         hasCode += map->initialCapacity;  
  156.     MyListIterator* it = createMyListIterator(map->entryList[hasCode]);  
  157.     int re = 0;  
  158.     while (myListIteratorHasNext(it)) {  
  159.         Entry * entry = (Entry *) (myListIteratorNext(it));  
  160.         if ((*(map->equal))(entry->key, key)) {  
  161.             myListRemoveDataAt(map->entryList[hasCode], it->count - 1);  
  162.             re = 1;  
  163.             (map->size)--;  
  164.             break;  
  165.         }  
  166.     }  
  167.     freeMyListIterator(it);  
  168.     return re;  
  169. }  
  170.   
  171. void myFree(Entry * p){  
  172.     free(p);  
  173. }  
  174.   
  175. //释放HashMap  
  176. void freeMyHashMap(MyHashMap * map) {  
  177.     myHashMapOutput(map, myFree);  
  178.     for (int i = 0; i < map->initialCapacity; i++) {  
  179.         freeMyList(map->entryList[i]);  
  180.     }  
  181.     free(map->entryList);  
  182.     free(map);  
  183. }  
  184.   
  185. //遍历  
  186. void myHashMapOutput(MyHashMap *map, void(*pt)(Entry*)) {  
  187.     MyHashMapEntryIterator* iterator = createMyHashMapEntryIterator(map);  
  188.     while (myHashMapEntryIteratorHasNext(iterator)) {  
  189.         pt(myHashMapEntryIteratorNext(iterator));  
  190.     }  
  191.     freeMyHashMapEntryIterator(iterator);  
  192. }  

测试文件

[cpp]  view plain  copy
  1. /************************* 
  2. *** File main.c 
  3. *** test for MyHashMap 
  4. **************************/  
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include "myEqual.h"  
  8. #include "myHashCode.h"  
  9. #include "myHashMap.h"  
  10.   
  11. #define S 10  
  12.   
  13. char* strs[S]=  
  14. {  
  15.     "abc",  
  16.     "qq",  
  17.     "hello",  
  18.     "abc",  
  19.     "lmy",  
  20.     "ab",  
  21.     "qq",  
  22.     "lqw",  
  23.     "sww",  
  24.     "lqw"  
  25. };  
  26.   
  27.   
  28. int main()  
  29. {  
  30.   
  31.     int*  data = malloc(sizeof(int)* S);  
  32.     for (int i=0; i<S; i++)  
  33.     {  
  34.         data[i]=i;  
  35.     }  
  36.   
  37.     //创建映射需要指定两个函数,hashCode函数和equal函数。  
  38.     MyHashMap * map = createMyHashMap(myHashCodeString, myEqualString);  
  39.   
  40.     //插入数据  
  41.     for (int i=0; i<S; i++)  
  42.     {  
  43.         myHashMapPutData(map, strs[i], &data[i]);  
  44.     }  
  45.   
  46.     //输出大小  
  47.     printf("size=%d\n",myHashMapGetSize(map));  
  48.   
  49.     //测试删除  
  50.     myHashMapRemoveDataByKey(map,"qq");  
  51.     myHashMapRemoveDataByKey(map,"ab");  
  52.     myHashMapRemoveDataByKey(map,"qwert");  
  53.   
  54.     //输出大小  
  55.     printf("after remove size=%d\n",myHashMapGetSize(map));  
  56.   
  57.     //遍历  
  58.     MyHashMapEntryIterator * it = createMyHashMapEntryIterator(map);  
  59.     while(myHashMapEntryIteratorHasNext(it))  
  60.     {  
  61.         Entry * pp= myHashMapEntryIteratorNext(it);  
  62.         char * key = pp-> key;  
  63.         int * value = pp->value;  
  64.         printf("%s(%d)\n", key, *value);  
  65.     }  
  66.     //释放遍历器  
  67.     freeMyHashMapEntryIterator(it);  
  68.   
  69.     //释放映射  
  70.     freeMyHashMap(map);  
  71.   
  72.     //释放数据  
  73.     free(data);  
  74.     return 0;  
  75. }  
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值