diff --git a/APP_Framework/Applications/app_test/test_hash/01.png b/APP_Framework/Applications/app_test/test_hash/01.png new file mode 100755 index 000000000..7a5360aa0 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_hash/01.png differ diff --git a/APP_Framework/Applications/app_test/test_hash/02.png b/APP_Framework/Applications/app_test/test_hash/02.png new file mode 100755 index 000000000..6279e3feb Binary files /dev/null and b/APP_Framework/Applications/app_test/test_hash/02.png differ diff --git a/APP_Framework/Applications/app_test/test_hash/03.png b/APP_Framework/Applications/app_test/test_hash/03.png new file mode 100755 index 000000000..b9b09f332 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_hash/03.png differ diff --git a/APP_Framework/Applications/app_test/test_hash/04.png b/APP_Framework/Applications/app_test/test_hash/04.png new file mode 100755 index 000000000..85ba6fd04 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_hash/04.png differ diff --git a/APP_Framework/Applications/app_test/test_hash/05.png b/APP_Framework/Applications/app_test/test_hash/05.png new file mode 100755 index 000000000..992e0117c Binary files /dev/null and b/APP_Framework/Applications/app_test/test_hash/05.png differ diff --git a/APP_Framework/Applications/app_test/test_hash/06.png b/APP_Framework/Applications/app_test/test_hash/06.png new file mode 100755 index 000000000..781eadd11 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_hash/06.png differ 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 old mode 100644 new mode 100755 index 876cd5d08..e6cd1f8d8 --- a/APP_Framework/Applications/app_test/test_hash/README.md +++ b/APP_Framework/Applications/app_test/test_hash/README.md @@ -1,19 +1,14 @@ -# 基于cortex-m3-emulator实现哈希表并测试验证## - +# 基于cortex-m3-emulator实现哈希表并测试验证 ## 1. 简介 -利用c语言实现了哈希表(HashMap),包括添加键值对(Put),获取键对应的值(Get), 删除健(Delete),清空哈希表(Clear), 迭代遍历哈希表(hashMapIterator)等功能 -操作。 +利用c语言实现了哈希表(HashMap),包括添加键值对(Put),获取键对应的值(Get), 删除健(Delete),清空哈希表(Clear)等功能。参考了比赛提供的示例代码,通过使用与比赛截然不同的方法——线性探测法来解决哈希冲突。 -利用数组(Entry)作为存储空间,利用链表(*next)解决冲突。当哈希表的大小超过数组大小后,为避免发生冲突过多的情况,可以对哈希表扩容。 ## 2. 数据结构设计说明 键值对结构 typedef struct entry { void * key; // 键 void * value; // 值 - struct entry * next; // 冲突链表 }*Entry; - 哈希结构 typedef struct hashMap { int size; // 当前大小 @@ -28,7 +23,6 @@ typedef struct hashMap { Exists exists; // 判断键是否存在 Boolean autoAssign; // 设定是否根据当前数据量动态调整内存大小,默认开启 }*HashMap; - 包括以下函数功能,分别为: `createHashMap`:创建一个哈希结构 `defaultPut`:添加键值对 @@ -38,21 +32,19 @@ typedef struct hashMap { `defaultClear`:清空Map的函数类型 `resetHashMap`:重新构建哈希表 - ## 3. 测试程序说明 -测试了哈希表的插入键值对(Put),判断键是否存在(Exist),获取键对应的值(Get), 删除健(Delete),迭代遍历哈希表(hashMapIterator),清空哈希表(Clear)等操作。 -并展示了利用链地址法解决哈希冲突的示例, 两个不同的人(Bob和Li Ming)的hashcode相同。 +测试了哈希表的插入键值对(Put),判断键是否存在(Exist),获取键对应的值(Get), 删除健(Delete)等操作。 + ## 4. 运行结果(##需结合运行测试截图按步骤说明##) -![image](ConfigOpen.png) -打开menuconfig之后,将test_hash_map开启(y),保存后退出 +4.1打开menuconfig之后,将test_hash_map开启(y),保存后退出。 +![image](01.png) +![image](02.png) +![image](03.png) +![image](04.png) -![image](CompileSuccess.png) -编译XiZi-cortex-m3-emulator.elf成功 - -![image](ShellCommand.png) -启动qemu模拟Xiuos操作系统,验证TestHash注册Shell命令 - -![image](TestHash.png) -执行TestHash命令,打印测试结果。 +4.2编译XiZi-cortex-m3-emulator.elf成功。 +![image](05.png) +4.3启动qemu模拟Xiuos操作系统,验证TestHash注册Shell命令。执行TestHash命令,打印测试结果。 +![image](06.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 old mode 100644 new mode 100755 index d6eabc4c7..7d0bb1a9e --- a/APP_Framework/Applications/app_test/test_hash/test_hash.c +++ b/APP_Framework/Applications/app_test/test_hash/test_hash.c @@ -2,12 +2,11 @@ /** * @file: test_hash.c * @brief: a application of test hash function -* @version: 3.0 -* @author: Yao wenying -* @date: 2023/05/26 +* @version: 1.0 +* @author: Li chunji And Li zihao +* @date: 2023/09/15 */ -#include #include"test_hash.h" int defaultHashCode(HashMap hashMap, let key) { @@ -34,17 +33,13 @@ void resetHashMap(HashMap hashMap, int listSize) { // 键值对临时存储空间 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; + for(int index=0;indexlistSize;index++) + { + tempList[index].key = hashMap->list[index].key; + tempList[index].value = hashMap->list[index].value; } - freeHashMapIterator(&iterator); // 清除原有键值对数据 hashMap->size = 0; @@ -52,13 +47,6 @@ void resetHashMap(HashMap hashMap, int listSize) { 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; - } - } } // 更改内存大小 @@ -73,7 +61,6 @@ void resetHashMap(HashMap hashMap, int listSize) { for (int i = 0; i < hashMap->listSize; i++) { hashMap->list[i].key = NULL; hashMap->list[i].value = NULL; - hashMap->list[i].next = NULL; } // 将所有键值对重新写入内存 @@ -84,60 +71,46 @@ void resetHashMap(HashMap hashMap, int listSize) { } void defaultPut(HashMap hashMap, let key, let value) { - // 获取哈希值 - int index = hashMap->hashCode(hashMap, key); + // 获取哈希值 + 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 { + 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; - }; + int cur = (index+1) % hashMap->listSize; + while(hashMap->list[cur].key != NULL) + { + cur = (cur + 1) % hashMap->listSize; + } - // 发生冲突则创建节点挂到相应位置的next上 - Entry entry = newEntry(); - entry->key = key; - entry->value = value; - entry->next = hashMap->list[index].next; - hashMap->list[index].next = entry; - hashMap->size++; - } + hashMap->size++; + hashMap->list[index].key = key; + hashMap->list[index].value = value; + } - if (hashMap->autoAssign && hashMap->size >= hashMap->listSize) { - - // 内存扩充至原来的两倍 - // *注: 扩充时考虑的是当前存储元素数量与存储空间的大小关系,而不是存储空间是否已经存满, - // 例如: 存储空间为10,存入了10个键值对,但是全部冲突了,所以存储空间空着9个,其余的全部挂在一个上面, - // 这样检索的时候和遍历查询没有什么区别了,可以简单这样理解,当我存入第11个键值对的时候一定会发生冲突, - // 这是由哈希函数本身的特性(取模)决定的,冲突就会导致检索变慢,所以这时候扩充存储空间,对原有键值对进行 - // 再次散列,会把冲突的数据再次分散开,加快索引定位速度。 - resetHashMap(hashMap, hashMap->listSize * 2); - } + if (hashMap->autoAssign && hashMap->size >= hashMap->listSize) { + 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; + 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; + } + index++; + entry = &hashMap->list[index % hashMap->listSize]; + } + } + return NULL; } let defaultRemove(HashMap hashMap, let key) { @@ -146,37 +119,29 @@ let defaultRemove(HashMap hashMap, let key) { if (entry->key == NULL) { return NULL; } - let entryKey = entry->key; + let entryKey = 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; - } + 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); + Entry entry = &hashMap->list[(index+1)%hashMap->listSize]; + while (entry != NULL) { + if (hashMap->equal(entry->key, key)) { + hashMap->size--; + entry->key = NULL; + entry->value = NULL; result = True; break; - } - p = entry; - entry = entry->next; - }; + } + index++; + entry = &hashMap->list[index % hashMap->listSize]; + } + } // 如果空间占用不足一半,则释放多余内存 @@ -187,107 +152,61 @@ let defaultRemove(HashMap hashMap, let key) { } 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; - } + 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; + } + index++; + entry = &hashMap->list[index % hashMap->listSize]; + } + 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; + + // 释放存储空间 + 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; + 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 = 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) @@ -305,19 +224,20 @@ void TestHash() { 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); - } + for(int index=0;indexlistSize;index++) + { + if(defaultExists(map, map->list[index].key)) + { + printf("{ key: %s, key: %s, hashcode: %d }\n", + (char *)map->list[index].key, (char *)map->list[index].value, map->hashCode); + } + } + + 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); -} - -PRIV_SHELL_CMD_FUNCTION(TestHash, Implement hash_map, PRIV_SHELL_CMD_MAIN_ATTR); \ No newline at end of file +} \ 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 old mode 100644 new mode 100755 index 3f7358411..e638951fa --- a/APP_Framework/Applications/app_test/test_hash/test_hash.h +++ b/APP_Framework/Applications/app_test/test_hash/test_hash.h @@ -1,13 +1,14 @@ /** -* @file: test_hash.h -* @brief: a application of test hash function -* @version: 3.0 -* @author: Yao wenying -* @date: 2023/05/26 +* @file: test_hash.c +* @brief: an application of test hash function +* @version: 1.0 +* @author: Li chunji And Li zihao +* @date: 2023/9/15 */ + #ifndef __HASHMAP_H__ #define __HASHMAP_H__ @@ -31,7 +32,6 @@ typedef enum _Boolean Boolean; typedef struct entry { let key; // 键 let value; // 值 - struct entry * next; // 冲突链表 }*Entry; #define newEntry() NEW(struct entry) @@ -77,15 +77,9 @@ typedef struct hashMap { 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); @@ -114,16 +108,5 @@ 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