diff --git a/APP_Framework/Applications/app_test/test_hash/CompileSuccess.png b/APP_Framework/Applications/app_test/test_hash/CompileSuccess.png deleted file mode 100644 index 04caae4d1..000000000 Binary files a/APP_Framework/Applications/app_test/test_hash/CompileSuccess.png and /dev/null differ diff --git a/APP_Framework/Applications/app_test/test_hash/ConfigOpen.png b/APP_Framework/Applications/app_test/test_hash/ConfigOpen.png deleted file mode 100644 index b62acec61..000000000 Binary files a/APP_Framework/Applications/app_test/test_hash/ConfigOpen.png and /dev/null differ diff --git a/APP_Framework/Applications/app_test/test_hash/README.md b/APP_Framework/Applications/app_test/test_hash/README.md index 876cd5d08..ec305e272 100644 --- a/APP_Framework/Applications/app_test/test_hash/README.md +++ b/APP_Framework/Applications/app_test/test_hash/README.md @@ -1,58 +1,78 @@ # 基于cortex-m3-emulator实现哈希表并测试验证## ## 1. 简介 -利用c语言实现了哈希表(HashMap),包括添加键值对(Put),获取键对应的值(Get), 删除健(Delete),清空哈希表(Clear), 迭代遍历哈希表(hashMapIterator)等功能 -操作。 +使用c语言实现hash表,实现hash表的基本操作,包括查找、删除、插入等。 +使用链表法来解决hash冲突的问题,链表为双向链表。 +hash函数使用murmurhash2。 +哈希表初始的大小为16,当装载因子大于0.7时会进行2倍扩容。 -利用数组(Entry)作为存储空间,利用链表(*next)解决冲突。当哈希表的大小超过数组大小后,为避免发生冲突过多的情况,可以对哈希表扩容。 +定义结构体来存储键值对。 ## 2. 数据结构设计说明 -键值对结构 -typedef struct entry { - void * key; // 键 - void * value; // 值 - struct entry * next; // 冲突链表 -}*Entry; - -哈希结构 -typedef struct hashMap { - int size; // 当前大小 - int listSize; // 有效空间大小 - HashCode hashCode; // 哈希函数 - Equal equal; // 判等函数 - Entry list; // 存储区域 - Put put; // 添加键的函数 - Get get; // 获取键对应值的函数 - Remove remove; // 删除键 - Clear clear; // 清空Map - Exists exists; // 判断键是否存在 - Boolean autoAssign; // 设定是否根据当前数据量动态调整内存大小,默认开启 -}*HashMap; - -包括以下函数功能,分别为: -`createHashMap`:创建一个哈希结构 -`defaultPut`:添加键值对 -`defaultGet`:获取键对应值 -`defaultRemove`:删除指定键的键值对 -`defaultExists`:判断键值是否存在 -`defaultClear`:清空Map的函数类型 -`resetHashMap`:重新构建哈希表 - +键值对结构体,使用void *指针存储键和值。使用双向链表构建冲突链表。 +``` +tyepdef struct hashNode{ + const void * key; + const void * value; + entry * pre; + entry * next; +}*entry; +``` +--------- +哈希表结构体 +``` +typedef struct hashmap +{ + entry *entryList; // 键值对 头结点数组 + unsigned int size; // hash表中的有效元素个数 + unsigned int len; // 数组的大小 + float factor; // 装载因子 + unsigned int (*hash)(const void *, unsigned __int64, hashmap *);//哈希函数 + const void *(*get)(const void *, hashmap *); // 获得元素 + void (*push)(const void *, const void *, hashmap *); // 插入元素 + void (*clear)(hashmap *); // 清空整个hash表 + int (*isEmpty)(hashmap *); // 检查hash表是否为空 + void (*del)(const void *, hashmap *); // 删除元素 + int (*keyEqual)(const void *, const void *); // 检查key值是否相同 +} *HashMap; +``` +------------- +遍历用的结构体(迭代器) +``` +struct Iterator +{ + HashMap map; //哈希表指针 + Entry cur; // 当前指针 + unsigned int count; // 计数 + unsigned int index; // 索引 + int (*hasNext)(Iterator iter);//是否有下一个元素 + Entry *(*next)(Iterator iter);//获取下一个键值对 + void (*destroy)(Iterator iter);//销毁迭代器 +}; +``` ## 3. 测试程序说明 -测试了哈希表的插入键值对(Put),判断键是否存在(Exist),获取键对应的值(Get), 删除健(Delete),迭代遍历哈希表(hashMapIterator),清空哈希表(Clear)等操作。 -并展示了利用链地址法解决哈希冲突的示例, 两个不同的人(Bob和Li Ming)的hashcode相同。 +测试了哈希表的插入键值对(push),迭代遍历哈希表并打印等操作。 -## 4. 运行结果(##需结合运行测试截图按步骤说明##) +## 4. 运行结果 +打开menuconfig之后,将test_hash开启(y),保存后退出 ![image](ConfigOpen.png) -打开menuconfig之后,将test_hash_map开启(y),保存后退出 -![image](CompileSuccess.png) 编译XiZi-cortex-m3-emulator.elf成功 +![image](CompileSuccess.png) -![image](ShellCommand.png) 启动qemu模拟Xiuos操作系统,验证TestHash注册Shell命令 +(qemu-system-arm -M lm3s6965evb -nographic -kernel build/XiZi-cortex-m3-emulator.elf) +![image](ShellCommand.png) -![image](TestHash.png) -执行TestHash命令,打印测试结果。 +执行ShowHash命令,打印测试结果。 +![image](hashMapTest.png) +执行HashGet命令,打印测试结果。 +![image](HashPut.png) + +执行HashPut命令,打印测试结果。 +![image](HashPut.png) + +执行HashDelete命令,打印测试结果。 +![image](HashDelete.png) diff --git a/APP_Framework/Applications/app_test/test_hash/ShellCommand.png b/APP_Framework/Applications/app_test/test_hash/ShellCommand.png deleted file mode 100644 index f9338e7e1..000000000 Binary files a/APP_Framework/Applications/app_test/test_hash/ShellCommand.png and /dev/null differ diff --git a/APP_Framework/Applications/app_test/test_hash/TestHash.png b/APP_Framework/Applications/app_test/test_hash/TestHash.png deleted file mode 100644 index 3170edfef..000000000 Binary files a/APP_Framework/Applications/app_test/test_hash/TestHash.png and /dev/null differ diff --git a/APP_Framework/Applications/app_test/test_hash/test_hash.c b/APP_Framework/Applications/app_test/test_hash/test_hash.c index d6eabc4c7..7d2459e22 100644 --- a/APP_Framework/Applications/app_test/test_hash/test_hash.c +++ b/APP_Framework/Applications/app_test/test_hash/test_hash.c @@ -1,323 +1,81 @@ - /** -* @file: test_hash.c -* @brief: a application of test hash function -* @version: 3.0 -* @author: Yao wenying -* @date: 2023/05/26 -*/ + * @file test_hash.c + * @author zhangchongke (senorisky@126.com) + * @brief C language to implement the hash table + * @version 0.1 + * @date 2023-09-17 + * + * @copyright Copyright (c) 2023 + * + */ #include -#include"test_hash.h" - -int defaultHashCode(HashMap hashMap, let key) { - char * k = (char *)key; - unsigned long h = 0; - while (*k) { - h = (h << 4) + *k++; - unsigned long g = h & 0xF0000000L; - if (g) { - h ^= g >> 24; - } - h &= ~g; - } - return h % hashMap->listSize; +#include "test_hash.h" +HashMapType CreateDefaultHashMap() { + HashMapType map = CreateHashMap(); + map->Push("1", "dhu", map); + map->Push("2", "edu", map); + map->Push("3", "cn", map); + map->Push("4", "YES", map); + map->Push("5", "Welcome", map); + map->Push("6", "Congradualation", map); + return map; } - -Boolean defaultEqual(let key1, let key2) { - return strcmp((string)key1, (string)key2) ? False : True; -} - -void resetHashMap(HashMap hashMap, int listSize) { - - if (listSize < 8) return; - - // 键值对临时存储空间 - Entry tempList = newEntryList(hashMap->size); - - HashMapIterator iterator = createHashMapIterator(hashMap); - int length = hashMap->size; - for (int index = 0; hasNextHashMapIterator(iterator); index++) { - // 迭代取出所有键值对 - iterator = nextHashMapIterator(iterator); - tempList[index].key = iterator->entry->key; - tempList[index].value = iterator->entry->value; - tempList[index].next = NULL; - } - freeHashMapIterator(&iterator); - - // 清除原有键值对数据 - hashMap->size = 0; - for (int i = 0; i < hashMap->listSize; i++) { - Entry current = &hashMap->list[i]; - current->key = NULL; - current->value = NULL; - if (current->next != NULL) { - while (current->next != NULL) { - Entry temp = current->next->next; - free(current->next); - current->next = temp; - } - } - } - - // 更改内存大小 - hashMap->listSize = listSize; - Entry relist = (Entry)realloc(hashMap->list, hashMap->listSize * sizeof(struct entry)); - if (relist != NULL) { - hashMap->list = relist; - relist = NULL; - } - - // 初始化数据 - for (int i = 0; i < hashMap->listSize; i++) { - hashMap->list[i].key = NULL; - hashMap->list[i].value = NULL; - hashMap->list[i].next = NULL; - } - - // 将所有键值对重新写入内存 - for (int i = 0; i < length; i++) { - hashMap->put(hashMap, tempList[i].key, tempList[i].value); - } - free(tempList); -} - -void defaultPut(HashMap hashMap, let key, let value) { - // 获取哈希值 - int index = hashMap->hashCode(hashMap, key); - - if (hashMap->list[index].key == NULL) { - hashMap->size++; - // 该地址为空时直接存储 - hashMap->list[index].key = key; - hashMap->list[index].value = value; - } - else { - - Entry current = &hashMap->list[index]; - while (current != NULL) { - if (hashMap->equal(key, current->key)) { - // 对于键值已经存在的直接覆盖 - current->value = value; - return; - } - current = current->next; - }; - - // 发生冲突则创建节点挂到相应位置的next上 - Entry entry = newEntry(); - entry->key = key; - entry->value = value; - entry->next = hashMap->list[index].next; - hashMap->list[index].next = entry; - hashMap->size++; - } - - if (hashMap->autoAssign && hashMap->size >= hashMap->listSize) { - - // 内存扩充至原来的两倍 - // *注: 扩充时考虑的是当前存储元素数量与存储空间的大小关系,而不是存储空间是否已经存满, - // 例如: 存储空间为10,存入了10个键值对,但是全部冲突了,所以存储空间空着9个,其余的全部挂在一个上面, - // 这样检索的时候和遍历查询没有什么区别了,可以简单这样理解,当我存入第11个键值对的时候一定会发生冲突, - // 这是由哈希函数本身的特性(取模)决定的,冲突就会导致检索变慢,所以这时候扩充存储空间,对原有键值对进行 - // 再次散列,会把冲突的数据再次分散开,加快索引定位速度。 - resetHashMap(hashMap, hashMap->listSize * 2); - } -} - -let defaultGet(HashMap hashMap, let key) { - if (hashMap->exists(hashMap, key)) { - int index = hashMap->hashCode(hashMap, key); - Entry entry = &hashMap->list[index]; - while (entry != NULL) { - if (hashMap->equal(entry->key, key)) { - return entry->value; - } - entry = entry->next; - } - } - return NULL; -} - -let defaultRemove(HashMap hashMap, let key) { - int index = hashMap->hashCode(hashMap, key); - Entry entry = &hashMap->list[index]; - if (entry->key == NULL) { - return NULL; - } - let entryKey = entry->key; - Boolean result = False; - if (hashMap->equal(entry->key, key)) { - hashMap->size--; - if (entry->next != NULL) { - Entry temp = entry->next; - entry->key = temp->key; - entry->value = temp->value; - entry->next = temp->next; - free(temp); - } - else { - entry->key = NULL; - entry->value = NULL; - } - result = True; - } - else { - Entry p = entry; - entry = entry->next; - while (entry != NULL) { - if (hashMap->equal(entry->key, key)) { - hashMap->size--; - p->next = entry->next; - free(entry); - result = True; - break; - } - p = entry; - entry = entry->next; - }; - } - - // 如果空间占用不足一半,则释放多余内存 - if (result && hashMap->autoAssign && hashMap->size < hashMap->listSize / 2) { - resetHashMap(hashMap, hashMap->listSize / 2); - } - return entryKey; -} - -Boolean defaultExists(HashMap hashMap, let key) { - int index = hashMap->hashCode(hashMap, key); - Entry entry = &hashMap->list[index]; - if (entry->key == NULL) { - return False; - } - else { - while (entry != NULL) { - if (hashMap->equal(entry->key, key)) { - return True; - } - entry = entry->next; - } - return False; - } -} - -void defaultClear(HashMap hashMap) { - for (int i = 0; i < hashMap->listSize; i++) { - // 释放冲突值内存 - Entry entry = hashMap->list[i].next; - while (entry != NULL) { - Entry next = entry->next; - free(entry); - entry = next; - } - hashMap->list[i].next = NULL; - } - // 释放存储空间 - free(hashMap->list); - hashMap->list = NULL; - hashMap->size = -1; - hashMap->listSize = 0; -} - -HashMap createHashMap(HashCode hashCode, Equal equal) { - HashMap hashMap = newHashMap(); - if (hashMap == NULL) { - return NULL; - } - hashMap->size = 0; - hashMap->listSize = 8; - hashMap->hashCode = hashCode == NULL ? defaultHashCode : hashCode; - hashMap->equal = equal == NULL ? defaultEqual : equal; - hashMap->exists = defaultExists; - hashMap->get = defaultGet; - hashMap->put = defaultPut; - hashMap->remove = defaultRemove; - hashMap->clear = defaultClear; - hashMap->autoAssign = True; - - // 起始分配8个内存空间,溢出时会自动扩充 - hashMap->list = newEntryList(hashMap->listSize); - if (hashMap->list == NULL) { - return NULL; - } - Entry p = hashMap->list; - for (int i = 0; i < hashMap->listSize; i++) { - p[i].key = p[i].value = p[i].next = NULL; - } - return hashMap; -} - -HashMapIterator createHashMapIterator(HashMap hashMap) { - HashMapIterator iterator = newHashMapIterator(); - if (iterator == NULL) { - return NULL; - } - iterator->hashMap = hashMap; - iterator->count = 0; - iterator->hashCode = -1; - iterator->entry = NULL; - return iterator; -} - -Boolean hasNextHashMapIterator(HashMapIterator iterator) { - return iterator->count < iterator->hashMap->size ? True : False; -} - -HashMapIterator nextHashMapIterator(HashMapIterator iterator) { - if (hasNextHashMapIterator(iterator)) { - if (iterator->entry != NULL && iterator->entry->next != NULL) { - iterator->count++; - iterator->entry = iterator->entry->next; - return iterator; - } - while (++iterator->hashCode < iterator->hashMap->listSize) { - Entry entry = &iterator->hashMap->list[iterator->hashCode]; - if (entry->key != NULL) { - iterator->count++; - iterator->entry = entry; - break; - } - } - } - return iterator; -} - -void freeHashMapIterator(HashMapIterator * iterator) { - free(*iterator); - *iterator = NULL; -} - -#define Put(map, key, value) map->put(map, (void *)key, (void *)value); -#define Get(map, key) (char *)map->get(map, (void *)key) -#define Remove(map, key) map->remove(map, (void *)key) -#define Existe(map, key) map->exists(map, (void *)key) - -void TestHash() { - HashMap map = createHashMap(NULL, NULL); - Put(map, "000123", "Annie"); - Put(map, "000245", "Bob"); - Put(map, "000284", "Daniel"); - Put(map, "000281", "Luna"); - Put(map, "000587", "Yao"); - Put(map, "000985", "Li Ming"); - Put(map, "000852", "Janne"); - - printf("print the key-values in hashmap:\n"); - HashMapIterator iterator = createHashMapIterator(map); - while (hasNextHashMapIterator(iterator)) { - iterator = nextHashMapIterator(iterator); - printf("{ key: %s, key: %s, hashcode: %d }\n", - (char *)iterator->entry->key, (char *)iterator->entry->value, iterator->hashCode); +void Show(HashMapType map) { + printf("key\t\t\tvalue\t\thashValue\n"); + Iterator iter = GetIterator(map); + HashNodeType node = NULL; + while (iter->HashNext(iter)) { + node = iter->Next(iter); + printf("%s\t\t\t%s\t\t\t%d\n", (char*)node->key, (char*)node->value, map->Hash(node->key, strlen(node->key), map)); } - printf("key: 000852, exists: %s\n", Existe(map, "000852") ? "true" : "false"); - printf("000852: %s\n", Get(map, "000852")); - printf("remove 000852 %s\n", Remove(map, "000852") ? "true" : "false"); - printf("key: 000852, exists: %s\n", Existe(map, "000852") ? "true" : "false"); - - map->clear(map); - freeHashMapIterator(&iterator); } +void ShowHash() { + HashMapType map = CreateDefaultHashMap(); + printf("all the operations are based on the default hash_map bellow\nall the operations will just change the map temporarily\n"); + printf("show all the elements in the default hash_map with iterator\n"); + Show(map); +} +void HashPut(int args, char* arg1[]) { + if (args != 3) { + printf("you can only put one key-value once a time\n"); + } + HashMapType map = CreateDefaultHashMap(); + map->Push(arg1[1], arg1[2], map); + Show(map); +} +void HashDelete(int args, char* arg1[]) { + if (args != 2) { + printf("you can only delete one element once a time\n"); + } + HashMapType map = CreateDefaultHashMap(); + map->Del(arg1[1], map); + Show(map); +} +void HashClear() { + HashMapType map = CreateDefaultHashMap(); + map->Clear(map); + Show(map); +} +void HashGet(int args, char* arg1[]) { + if (args != 2) { + printf("you can only get one element once a time\n"); + } + HashMapType map = CreateDefaultHashMap(); + const char* value = map->Get(arg1[1], map); + printf("%s", arg1[1]); + if (value == NULL) { + printf("there is no key called %s\n", (char*)arg1[1]); + } + else { + unsigned int len = strlen(arg1[1]); + unsigned int hash = map->Hash(arg1[1], len, map); + printf("the value is %s\nthe hash of value is %d\n", value, hash); + } -PRIV_SHELL_CMD_FUNCTION(TestHash, Implement hash_map, PRIV_SHELL_CMD_MAIN_ATTR); \ No newline at end of file +} +PRIV_SHELL_CMD_FUNCTION(ShowHash, show default hash_map, PRIV_SHELL_CMD_MAIN_ATTR); +PRIV_SHELL_CMD_FUNCTION(HashGet, test hash_get, PRIV_SHELL_CMD_MAIN_ATTR); +PRIV_SHELL_CMD_FUNCTION(HashClear, test hash_clear, PRIV_SHELL_CMD_MAIN_ATTR); +PRIV_SHELL_CMD_FUNCTION(HashDelete, test hash_delete, PRIV_SHELL_CMD_MAIN_ATTR); +PRIV_SHELL_CMD_FUNCTION(HashPut, test hash_put, PRIV_SHELL_CMD_MAIN_ATTR); \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_hash/test_hash.h b/APP_Framework/Applications/app_test/test_hash/test_hash.h index 3f7358411..c3225f3fa 100644 --- a/APP_Framework/Applications/app_test/test_hash/test_hash.h +++ b/APP_Framework/Applications/app_test/test_hash/test_hash.h @@ -1,129 +1,313 @@ - /** -* @file: test_hash.h -* @brief: a application of test hash function -* @version: 3.0 -* @author: Yao wenying -* @date: 2023/05/26 -*/ + * @file test_hash.h + * @author zhangchongke (senorisky@126.com) + * @brief C language to implement the hash table + * @version 0.1 + * @date 2023-09-17 + * + * @copyright Copyright (c) 2023 + * + */ +#include +#include +#include +#define BASE 16 // 初始hash表大小 -#ifndef __HASHMAP_H__ -#define __HASHMAP_H__ +typedef struct HashNode { + const void* value; // 值 + const void* key; // 键 + struct HashNode* next; + struct HashNode* pre; // 双向链表指针 +} *HashNodeType; -#include -#include -#include +typedef struct HashMap { + HashNodeType* entry_list; // 键值对 头结点数组 + unsigned int size; // hash表中的有效元素个数 + unsigned int len; // 数组的大小 + float factor; // 装载因子 + unsigned int (*Hash)(const void*, unsigned int len, struct HashMap*); + const void* (*Get)(const void*, struct HashMap*); // 获得元素 + void (*Push)(const void*, const void*, struct HashMap*); // 插入元素 + void (*Clear)(struct HashMap*); // 清空整个hash表 + int (*IsEmpty)(struct HashMap*); // 检查hash表是否为空 + void (*Del)(const void*, struct HashMap*); // 删除元素 + int (*KeyEqual)(const void*, const void*); // 检查key值是否相同 +} *HashMapType; +typedef struct Iter { + /* data */ + HashMapType map; + HashNodeType cur; // 当前指针 + unsigned int count; // 计数 + unsigned int index; // 索引 + int (*HashNext)(struct Iter* iter); // 是否有下一个元素 + HashNodeType(*Next)(struct Iter* iter); // 获取下一个键值对 + void (*Destroy)(struct Iter* iter); // 销毁迭代器 +} *Iterator; -// 实现数据的基本类型 -// 字符串类型 -#define string char * -#define newString(str) strcpy((char *)malloc(strlen(str) + 1), str) -#define NEW(type) (type *)malloc(sizeof(type)) +int IsEmpty(HashMapType map); +int HasNext(Iterator iter); +unsigned int Hash(const void* key, unsigned int len, HashMapType map); +int KeyEqual(const void* innerKey, const void* outerKey); +Iterator GetIterator(HashMapType map); +HashNodeType Next(Iterator iter); +const void* Get(const void* key, HashMapType map); +void Push(const void* key, const void* value, HashMapType map); +void Clear(HashMapType map); +void Del(const void* key, HashMapType map); +void IniteHashNodeTypeList(HashNodeType* list, unsigned int len); +void Destroy(struct Iter* iter); -// 布尔类型 -enum _Boolean { True = 1, False = 0 }; -typedef enum _Boolean Boolean; +int IsEmpty(HashMapType map) { + return map->size == 0; +} +int HasNext(Iterator iter) { -#define let void * + if (iter->count == iter->map->size) { + return 0; + } + return 1; +} +int KeyEqual(const void* innerKey, const void* outerKey) { + if (innerKey == NULL) { + return 0; + } + return !strcmp((const char*)innerKey, (const char*)outerKey); +} +void IniteHashNodeTypeList(HashNodeType* list, unsigned int len) { + int i = 0; + while (i < len) { + HashNodeType p = (HashNodeType)malloc(sizeof(struct HashNode)); + p->next = NULL; + p->key = NULL; + p->value = NULL; + list[i] = p; + i++; + } +} -typedef struct entry { - let key; // 键 - let value; // 值 - struct entry * next; // 冲突链表 -}*Entry; +// 使用murmur_hash2 +unsigned int Hash(const void* key, unsigned int len, HashMapType map) { + const unsigned int m = 0x5bd1e995; + unsigned int h, k; + h = 0 ^ len; + const unsigned char* data = (const unsigned char*)key; + while (len >= 4 && *data) { + k = *(unsigned int*)data; -#define newEntry() NEW(struct entry) -#define newEntryList(length) (Entry)malloc(length * sizeof(struct entry)) + k *= m; + k ^= k >> 24; + k *= m; -// 哈希结构 -typedef struct hashMap *HashMap; + h *= m; + h ^= k; -#define newHashMap() NEW(struct hashMap) + data += 4; + len -= 4; + } + switch (len) { + case 3: + h ^= data[2] << 16; + case 2: + h ^= data[1] << 8; + case 1: + h ^= data[0]; + h *= m; + } + h ^= h >> 13; + h *= m; + h ^= h >> 15; + return h % map->len; +} +Iterator GetIterator(HashMapType map) { + Iterator iter = (Iterator)malloc(sizeof(struct Iter)); + iter->HashNext = HasNext; + iter->Next = Next; + iter->count = 0; + iter->cur = map->entry_list[0]; + iter->map = map; + for (int i = 0; i < map->len; i++) { -// 哈希函数类型 -typedef int(*HashCode)(HashMap, let key); + if (map->entry_list[i]->next != NULL) { + iter->index = i; + iter->cur = map->entry_list[i]; + break; + } + } + return iter; +} +HashNodeType Next(Iterator iter) { + HashMapType map = iter->map; + if (iter->count >= map->size) { + return NULL; + } + if (iter->cur->next != NULL) { + iter->cur = iter->cur->next; + iter->count++; + return iter->cur; + } + unsigned int i = iter->index; + while (map->entry_list[i + 1]->next == NULL) { + i++; + } + iter->index = i + 1; + iter->cur = map->entry_list[i + 1]->next; + iter->count++; + return iter->cur; +} +const void* Get(const void* key, HashMapType map) { + if (key == NULL) + return NULL; + const char* tmp = (const char*)key; + unsigned int hash = map->Hash(key, strlen(tmp), map); + HashNodeType cur = map->entry_list[hash]; + while (cur->next != NULL) { + cur = cur->next; + if (map->KeyEqual(cur->key, key)) { + break; + } + /* code */ + } -// 判等函数类型 -typedef Boolean(*Equal)(let key1, let key2); + return cur->value; +} +void Push(const void* key, const void* value, HashMapType map) { + if (key == NULL) + return; + // 检查负载因子 负载因子过大 容易出现冲突,需要扩容来解决 + if (map->factor > 0.7) { + int oldLen = map->len; + map->len = oldLen * 2; + HashNodeType* oldList = map->entry_list; + map->entry_list = (HashNodeType*)malloc(map->len * sizeof(HashNodeType)); + if (map->entry_list == NULL) { + return; + } + // 初始化头指针数组 + IniteHashNodeTypeList(map->entry_list, map->len); + // 重新计算所有元素hash值 重新放置 + int i = 0; + while (i < oldLen) { + /* code */ + HashNodeType cur = NULL; + while (oldList[i]->next != NULL) { + cur = oldList[i]->next; + cur->pre->next = cur->next; + cur->next->pre = cur->pre; + unsigned int hash = map->Hash(cur->key, strlen((const char*)cur->key), map); + HashNodeType tail = map->entry_list[hash]; + while (tail->next != NULL) { + tail = tail->next; + } + tail->next = cur; + cur->next = NULL; + cur->pre = tail; + } + i++; + } + map->factor = map->size * 1.0 / map->len; + free(oldList); + } + unsigned int hash = map->Hash(key, strlen((const char*)key), map); + HashNodeType insert = (HashNodeType)malloc(sizeof(struct HashNode)); + if (insert == NULL) { + return; + } + insert->key = key; + insert->value = value; + HashNodeType cur = map->entry_list[hash]; + while (cur->next != NULL) {// 尾插法 + cur = cur->next; + if (map->KeyEqual(cur->key, key)) { // 出现一致的key 进行替换 + cur->pre->next = insert; + insert->pre = cur->pre; + insert->next = cur->next; + if (cur->next != NULL) + cur->next->pre = insert; + map->factor = map->size * 1.0 / map->len; + map->size++; + free(cur); + break; + } + } + if (cur->next == NULL) { + cur->next = insert; + insert->pre = cur; + insert->next = NULL; + map->factor = map->size * 1.0 / map->len; + map->size++; + } +} +void Destroy(struct Iter* iter) { + if (iter->cur) + free(iter->cur); + free(iter); +} -// 添加键函数类型 -typedef void(*Put)(HashMap hashMap, let key, let value); +// 清空所有元素,数组恢复初始大小 +void Clear(HashMapType map) { + int oldLen = map->len; + map->len = BASE; + HashNodeType* oldList = map->entry_list; + map->entry_list = (HashNodeType*)malloc(map->len * sizeof(HashNodeType)); + // 初始化头指针数组 + if (map->entry_list != NULL) { + IniteHashNodeTypeList(map->entry_list, BASE); + } + else { + return; + } + map->factor = 0; + map->size = 0; + // 删除所有元素 + int i = 0; + while (i < oldLen) { + /* code */ + HashNodeType cur = NULL; + while (oldList[i]->next != NULL) { + cur = oldList[i]->next; + cur->pre->next = cur->next; + cur->next->pre = cur->pre; + free(cur); + } + i++; + } + free(oldList); +} +void Del(const void* key, HashMapType map) { + if (key == NULL) + return; + unsigned int hash = map->Hash(key, strlen((const char*)key), map); + HashNodeType cur = map->entry_list[hash]; + while (cur->next != NULL) { + cur = cur->next; + if (map->KeyEqual(cur->key, key)) { + cur->pre->next = cur->next; + if (cur->next != NULL) + cur->next->pre = cur->pre; + map->size--; + free(cur); + break; + } + } + map->factor = map->size * 1.0 / map->len; + return; +} -// 获取键对应值的函数类型 -typedef let(*Get)(HashMap hashMap, let key); - -// 删除键的函数类型 -typedef let(*Remove)(HashMap hashMap, let key); - -// 清空Map的函数类型 -typedef void(*Clear)(HashMap hashMap); - -// 判断键值是否存在的函数类型 -typedef Boolean(*Exists)(HashMap hashMap, let key); - -typedef struct hashMap { - int size; // 当前大小 - int listSize; // 有效空间大小 - HashCode hashCode; // 哈希函数 - Equal equal; // 判等函数 - Entry list; // 存储区域 - Put put; // 添加键的函数 - Get get; // 获取键对应值的函数 - Remove remove; // 删除键 - Clear clear; // 清空Map - Exists exists; // 判断键是否存在 - Boolean autoAssign; // 设定是否根据当前数据量动态调整内存大小,默认开启 -}*HashMap; - -// 迭代器结构 -typedef struct hashMapIterator { - Entry entry; // 迭代器当前指向 - int count; // 迭代次数 - int hashCode; // 键值对的哈希值 - HashMap hashMap; -}*HashMapIterator; - -#define newHashMapIterator() NEW(struct hashMapIterator) - -// 默认哈希函数 -static int defaultHashCode(HashMap hashMap, let key); - -// 默认判断键值是否相等 -static Boolean defaultEqual(let key1, let key2); - -// 默认添加键值对 -static void defaultPut(HashMap hashMap, let key, let value); - -// 默认获取键对应值 -static let defaultGet(HashMap hashMap, let key); - -// 默认删除键 -static let defaultRemove(HashMap hashMap, let key); - -// 默认判断键是否存在 -static Boolean defaultExists(HashMap hashMap, let key); - -// 默认清空Map -static void defaultClear(HashMap hashMap); - -// 重新构建 -static void resetHashMap(HashMap hashMap, int listSize); - -// 创建一个哈希结构 -HashMap createHashMap(HashCode hashCode, Equal equal); - -// 创建哈希结构迭代器 -HashMapIterator createHashMapIterator(HashMap hashMap); - -// 迭代器是否有下一个 -Boolean hasNextHashMapIterator(HashMapIterator iterator); - -// 迭代到下一次 -HashMapIterator nextHashMapIterator(HashMapIterator iterator); - -// 释放迭代器内存 -void freeHashMapIterator(HashMapIterator * iterator); - -#endif // !__HASHMAP_H__ \ No newline at end of file +HashMapType CreateHashMap() { + HashMapType map = (HashMapType)malloc(sizeof(struct HashMap)); + map->Clear = Clear; + map->Get = Get; + map->Del = Del; + map->Push = Push; + map->Hash = Hash; + map->KeyEqual = KeyEqual; + map->IsEmpty = IsEmpty; + map->size = 0; + map->len = BASE; + map->factor = 0; + map->entry_list = (HashNodeType*)malloc(sizeof(HashNodeType) * BASE); + IniteHashNodeTypeList(map->entry_list, BASE); + return map; +} \ No newline at end of file diff --git a/APP_Framework/Applications/main.c b/APP_Framework/Applications/main.c index b10557a97..1f37a235d 100644 --- a/APP_Framework/Applications/main.c +++ b/APP_Framework/Applications/main.c @@ -19,7 +19,7 @@ extern int FrameworkInit(); extern void ApplicationOtaTaskInit(void); int main(void) { - printf("Hello, world! \n"); + printf("Hello, world! !\n"); FrameworkInit(); #ifdef APPLICATION_OTA ApplicationOtaTaskInit();