C語言實現通用數據結構之通用映射(HashMap)
本文實例為大傢分享瞭C語言實現通用數據結構之通用映射的具體代碼,供大傢參考,具體內容如下
這是在通用鏈表的基礎上實現的映射,關於鏈表的實現參見:C語言實現通用數據結構之通用鏈表。
註意映射中隻存儲瞭key和value的指針,沒有儲存實際的數據。
對於新的key類型來說,需要自定義HashCode函數和equal函數。
在HashSet的實現中給出瞭幾個常見的hashCode函數和equal函數。參見:c語言實現通用數據結構(四):通用集合。
頭文件:myHashMap.h
#ifndef MYHASHMAP_H_INCLUDED #define MYHASHMAP_H_INCLUDED #include "myList.h" #define DEFAULT_INITIAL_CAPACITY 16 #define DEFAULT_LOAD_FACTOR 0.75f typedef struct entry { void * key; void * value; } Entry; typedef struct myHashMap { int size; //大小 int initialCapacity; //初始容量 float loadFactor; //加載因子 int (*hashCode)(void *key); int (*equal)(void *key1,void *key2); MyList ** entryList; } MyHashMap; typedef struct myHashMapEntryIterator { int index; //第幾個鏈表 MyHashMap *map; MyNode *current; int count; //第幾個數據 } MyHashMapEntryIterator; //創建HashMap MyHashMap *createMyHashMap(int (*hashCode)(void *key),int (*equal)(void *key1,void *key2)); //使用全部參數創建HashMap MyHashMap *createMyHashMapForAll(int initialCapacity,float loadFactor,int (*hashCode)(void *key),int (*equal)(void *key1,void *key2)); //釋放HashMap void freeMyHashMap(MyHashMap * map); //是否包含某個key int myHashMapContainsKey(MyHashMap *const map,void * const key); //增加一條映射 void myHashMapPutData(MyHashMap *const map,void * const key,void * const value); //通過key得到數據,如果沒有數據則返回null void* myHashMapGetDataByKey(MyHashMap * const map,void *const key); //數據的容量 int myHashMapGetSize(const MyHashMap * const map); //創建Entry迭代器 MyHashMapEntryIterator* createMyHashMapEntryIterator( MyHashMap *const map); //釋放Entry迭代器 void freeMyHashMapEntryIterator(MyHashMapEntryIterator* iterator); //Entry迭代器是否有下一個 int myHashMapEntryIteratorHasNext(MyHashMapEntryIterator* iterator); //遍歷下一個Entry元素 Entry* myHashMapEntryIteratorNext(MyHashMapEntryIterator* iterator); //刪除一條數據,返回是否刪除成功 int myHashMapRemoveDataByKey(MyHashMap *const map,void * const key); //遍歷 void myHashMapOutput(MyHashMap *map, void(*pt)(Entry*)); #endif // MYHASHMAP_H_INCLUDED
源文件: myHashMap.c
#include "myHashMap.h" #include <stdlib.h> //某條Entry鏈表上是否包含某個key值。 Entry* listContainsEntry(MyList * list, void * key, int(*equal)(void *key1, void *key2)) { MyListIterator* it = createMyListIterator(list); while (myListIteratorHasNext(it)) { Entry * entry = (Entry *) (myListIteratorNext(it)); if (entry->key == key || (equal != NULL && (*equal)(entry->key, key))) { return entry; } } freeMyListIterator(it); return NULL; } void rebuildMyHashMap(MyHashMap * map) { int newSize = map->initialCapacity * 2; MyList **newentryList = (MyList **) malloc(sizeof(MyList*) * newSize); for (int i = 0; i < newSize; i++) { newentryList[i] = createMyList(); } MyHashMapEntryIterator* it = createMyHashMapEntryIterator(map); while (myHashMapEntryIteratorHasNext(it)) { Entry * entry = myHashMapEntryIteratorNext(it); int hasCode = (*(map->hashCode))(entry->key); hasCode %= newSize; if (hasCode < 0) hasCode += newSize; myListInsertDataAtLast(newentryList[hasCode], entry); } freeMyHashMapEntryIterator(it); for (int i = 0; i < map->initialCapacity; i++) { freeMyList(map->entryList[i]); } free(map->entryList); map->entryList = newentryList; map->initialCapacity = newSize; } //創建HashMap MyHashMap *createMyHashMap(int(*hashCode)(void *key), int(*equal)(void *key1, void *key2)) { MyHashMap *re = (MyHashMap *) malloc(sizeof(MyHashMap)); re->size = 0; re->loadFactor = DEFAULT_LOAD_FACTOR; re->initialCapacity = DEFAULT_INITIAL_CAPACITY; re->entryList = (MyList **) malloc(sizeof(MyList*) * re->initialCapacity); re->hashCode = hashCode; re->equal = equal; for (int i = 0; i < re->initialCapacity; i++) { re->entryList[i] = createMyList(); } return re; } //使用全部參數創建HashMap MyHashMap *createMyHashMapForAll(int initialCapacity, float loadFactor, int(*hashCode)(void *key), int(*equal)(void *key1, void *key2)) { MyHashMap *re = createMyHashMap(hashCode, equal); re->initialCapacity = initialCapacity; re->loadFactor = loadFactor; return re; } //是否包含某個key int myHashMapContainsKey(MyHashMap * const map, void * const key) { int hasCode = (*(map->hashCode))(key); hasCode %= map->initialCapacity; if (hasCode < 0) hasCode += map->initialCapacity; Entry * re = listContainsEntry(map->entryList[hasCode], key, map->equal); return re != NULL; } //增加一條映射 void myHashMapPutData(MyHashMap * const map, void * const key, void * const value) { int hasCode = (*(map->hashCode))(key); hasCode %= map->initialCapacity; if (hasCode < 0) hasCode += map->initialCapacity; Entry * re = listContainsEntry(map->entryList[hasCode], key, map->equal); if (re == NULL) { Entry * entry = (Entry*) malloc(sizeof(Entry)); entry->key = key; entry->value = value; myListInsertDataAtLast(map->entryList[hasCode], entry); (map->size)++; if (map->size > map->initialCapacity * map->loadFactor) { rebuildMyHashMap(map); } } else { re->value = value; } } //通過key得到數據,如果沒有數據則返回null void* myHashMapGetDataByKey(MyHashMap * const map, void * const key) { int hasCode = (*(map->hashCode))(key); hasCode %= map->initialCapacity; if (hasCode < 0) hasCode += map->initialCapacity; Entry * re = listContainsEntry(map->entryList[hasCode], key, map->equal); if (re == NULL) { return NULL; } return re->value; } //數據的容量 int myHashMapGetSize(const MyHashMap * const map) { return map->size; } //創建Entry迭代器 MyHashMapEntryIterator* createMyHashMapEntryIterator(MyHashMap * const map) { MyHashMapEntryIterator* re = (MyHashMapEntryIterator*) malloc( sizeof(MyHashMapEntryIterator)); re->count = 0; re->index = 0; re->map = map; re->current = map->entryList[0]->first; return re; } //釋放Entry迭代器 void freeMyHashMapEntryIterator(MyHashMapEntryIterator* iterator) { free(iterator); } //Entry迭代器是否有下一個 int myHashMapEntryIteratorHasNext(MyHashMapEntryIterator* iterator) { return iterator->count < iterator->map->size; } //遍歷下一個Entry元素 Entry* myHashMapEntryIteratorNext(MyHashMapEntryIterator* iterator) { (iterator->count)++; while (!(iterator->current)) { (iterator->index)++; iterator->current = iterator->map->entryList[iterator->index]->first; } Entry * re = (Entry *) iterator->current->data; iterator->current = iterator->current->next; return re; } //刪除一條數據,返回是否刪除成功 int myHashMapRemoveDataByKey(MyHashMap * const map, void * const key) { int hasCode = (*(map->hashCode))(key); hasCode %= map->initialCapacity; if (hasCode < 0) hasCode += map->initialCapacity; MyListIterator* it = createMyListIterator(map->entryList[hasCode]); int re = 0; while (myListIteratorHasNext(it)) { Entry * entry = (Entry *) (myListIteratorNext(it)); if ((*(map->equal))(entry->key, key)) { myListRemoveDataAt(map->entryList[hasCode], it->count - 1); re = 1; (map->size)--; break; } } freeMyListIterator(it); return re; } void myFree(Entry * p){ free(p); } //釋放HashMap void freeMyHashMap(MyHashMap * map) { myHashMapOutput(map, myFree); for (int i = 0; i < map->initialCapacity; i++) { freeMyList(map->entryList[i]); } free(map->entryList); free(map); } //遍歷 void myHashMapOutput(MyHashMap *map, void(*pt)(Entry*)) { MyHashMapEntryIterator* iterator = createMyHashMapEntryIterator(map); while (myHashMapEntryIteratorHasNext(iterator)) { pt(myHashMapEntryIteratorNext(iterator)); } freeMyHashMapEntryIterator(iterator); }
測試文件
/************************* *** File main.c *** test for MyHashMap **************************/ #include <stdio.h> #include <stdlib.h> #include "myEqual.h" #include "myHashCode.h" #include "myHashMap.h" #define S 10 char* strs[S]= { "abc", "qq", "hello", "abc", "lmy", "ab", "qq", "lqw", "sww", "lqw" }; int main() { int* data = malloc(sizeof(int)* S); for (int i=0; i<S; i++) { data[i]=i; } //創建映射需要指定兩個函數,hashCode函數和equal函數。 MyHashMap * map = createMyHashMap(myHashCodeString, myEqualString); //插入數據 for (int i=0; i<S; i++) { myHashMapPutData(map, strs[i], &data[i]); } //輸出大小 printf("size=%d\n",myHashMapGetSize(map)); //測試刪除 myHashMapRemoveDataByKey(map,"qq"); myHashMapRemoveDataByKey(map,"ab"); myHashMapRemoveDataByKey(map,"qwert"); //輸出大小 printf("after remove size=%d\n",myHashMapGetSize(map)); //遍歷 MyHashMapEntryIterator * it = createMyHashMapEntryIterator(map); while(myHashMapEntryIteratorHasNext(it)) { Entry * pp= myHashMapEntryIteratorNext(it); char * key = pp-> key; int * value = pp->value; printf("%s(%d)\n", key, *value); } //釋放遍歷器 freeMyHashMapEntryIterator(it); //釋放映射 freeMyHashMap(map); //釋放數據 free(data); return 0; }
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。
推薦閱讀:
- C語言實現通用數據結構之通用集合(HashSet)
- Java之HashMap案例詳解
- C語言實現通用數據結構之通用鏈表
- Java數據結構之HashMap和HashSet
- Java1.7全網最深入HashMap源碼解析