diff --git a/APP_Framework/Applications/app_test/Kconfig b/APP_Framework/Applications/app_test/Kconfig index 45df5f5d5..6f922d703 100644 --- a/APP_Framework/Applications/app_test/Kconfig +++ b/APP_Framework/Applications/app_test/Kconfig @@ -239,6 +239,10 @@ menu "test app" menuconfig USER_TEST_TIMER bool "Config test soft timer" default n + + menuconfig USER_TEST_HASH + bool "Config test hash" + default y endif endmenu diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index 1cf919846..c5fd51038 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -100,6 +100,10 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y) ifeq ($(CONFIG_USER_TEST_TIMER),y) SRC_FILES += test_timer.c endif + + ifeq ($(CONFIG_USER_TEST_HASH),y) + SRC_FILES += test_hash/test_hash.c + endif include $(KERNEL_ROOT)/compiler.mk endif diff --git a/APP_Framework/Applications/app_test/test_hash/README.md b/APP_Framework/Applications/app_test/test_hash/README.md new file mode 100644 index 000000000..39b7fb693 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_hash/README.md @@ -0,0 +1,156 @@ +# ##基于cortex-m3-emulator实现哈希表并测试验证## + +## 1. 简介 +实现哈希表,支持链地址法解决哈希冲突,并编写测试程序在shell终端打印结果 +因为没有说明哈希的具体实现完成程度,以个人理解程度实现,以熟悉热身为目的 + + +## 2. 数据结构设计说明 +```C +#define TABLE_SIZE 10//哈希表的长度,使用宏定义,有需要可直接更改 + +typedef struct Node { + int key; + int value; + struct Node* next; +} Node;//一个结点的数据类型,包含key,value,和指向下一个结点的指针 + +typedef struct HashTable { + Node** table; // 存储链表头指针的数组 +} HashTable; +``` + + +## 3. 测试程序说明 +包含两大部分函数 +1,初始化链表使用的函数 +```C +//创建一个结点,在添加键值对时使用 +Node* createNode(int key, int value) { + Node* newNode = (Node*)malloc(sizeof(Node)); + newNode->key = key; + newNode->value = value; + newNode->next = NULL; + return newNode; +} + +//初始化哈希表 +HashTable* createHashTable() { + HashTable* hashTable = (HashTable*)malloc(sizeof(HashTable)); + hashTable->table = (Node**)calloc(TABLE_SIZE, sizeof(Node*)); + return hashTable; +} + +// 哈希函数,计算键的索引 +int hashFunction(int key) { + return key % TABLE_SIZE; +} +``` +2,对链表进行更改的函数,共五个操作即五个函数 +```C +// 在哈希表中插入键值对 +void insert(HashTable* hashTable, int key, int value) { + int index = hashFunction(key); + + Node* newNode = createNode(key, value); + + if (hashTable->table[index] == NULL) { + hashTable->table[index] = newNode; + } else { + Node* current = hashTable->table[index]; + while (current->next != NULL) { + current = current->next; + } + current->next = newNode; + } +} + +// 在哈希表中查找是否有该键,有则返回1,无则返回0 +int find(HashTable* hashTable, int key) { + int index = hashFunction(key); + + Node* current = hashTable->table[index]; + while (current != NULL) { + if (current->key == key) { + return 1; + } + current = current->next; + } + + return 0; +} + +// 在哈希表中查找键对应的值,找到返回键对应的值,如果未找到返回-1 +int get(HashTable* hashTable, int key) { + int index = hashFunction(key); + + Node* current = hashTable->table[index]; + while (current != NULL) { + if (current->key == key) { + return current->value; + } + current = current->next; + } + + return -1; +} + +//将某一键值对的值改变为新的值,修改成功返回1,如果未找到该键值对返回0 +int change(HashTable* hashTable, int key , int oldValue , int newValue) { + int index = hashFunction(key); + + Node* current = hashTable->table[index]; + while (current != NULL) { + if (current->key == key && current->value == oldValue) { + current->value = newValue; + return 1; + } + current = current->next; + } + + return 0; +} + +//删除某一键值对,删除成功返回1,如果未找到该键值对返回0 +int deleteNode(HashTable* hashTable, int key , int value ) { + int index = hashFunction(key); + + Node* current = hashTable->table[index]; + Node* last = current; + if(current != NULL){ + if (current->key == key && current->value == value){ + hashTable->table[index] = current->next; + free(current); + return 1; + } + current = current->next; + } + + while (current != NULL) { + if (current->key == key && current->value == value) { + last->next=current->next; + free(current); + return 1; + } + last = current; + current = current->next; + + } + + return 0; +} +``` +### 测试思路:(测试代码即test_hash()函数中内容) +1,初始化了哈希表,随机选取了四个键值对进行插入 +2,测试通过键寻找值,分成两种情况,找到和未找到 +3,修改键值对的值,若找到键值对输出新的值,若找不到,显示未找到该键值对 +4,删除特定键值对,同时证明对后续结点不产生影响 + + +## 4. 运行结果(##需结合运行测试截图按步骤说明##) +![screenshot](screen.png) +1. 第一部分 插入了四个键值对 +2. 第二部分 寻找key 13,在哈希表中,显示值为66;寻找key 24, 不在哈希表中,显示未找到 +3. 第三部分 将键值对3,99修改成3,100,修改成功,显示新值为100;将键值对2,99修改成2,100,哈希表中不存在键值对2,99,失败. +4. 第四部分 删除键值对3,100,证明3,100消失,同时不影响后续结点。 +5. 最后释放哈希表占用内存 \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_hash/screen.png b/APP_Framework/Applications/app_test/test_hash/screen.png new file mode 100644 index 000000000..e22b25509 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_hash/screen.png 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 new file mode 100644 index 000000000..d08a83cee --- /dev/null +++ b/APP_Framework/Applications/app_test/test_hash/test_hash.c @@ -0,0 +1,218 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file: test_hash.c +* @brief: a application of hash function and hash test function +* @version: 1 +* @author: 樱园精机 +* @date: 2023/6/29 +*/ + +#include +#include +#include +#include +#ifdef ADD_XIZI_FETURES +#define TABLE_SIZE 10 + +// 定义哈希表中存储的元素结构 +typedef struct Node { + int key; + int value; + struct Node* next; +} Node; + +// 定义哈希表结构 +typedef struct HashTable { + Node** table; // 存储链表头指针的数组 +} HashTable; + +// 创建新节点 +Node* createNode(int key, int value) { + Node* newNode = (Node*)malloc(sizeof(Node)); + newNode->key = key; + newNode->value = value; + newNode->next = NULL; + return newNode; +} + +// 初始化哈希表 +HashTable* createHashTable() { + HashTable* hashTable = (HashTable*)malloc(sizeof(HashTable)); + hashTable->table = (Node**)calloc(TABLE_SIZE, sizeof(Node*)); + return hashTable; +} + +// 哈希函数,计算键的索引 +int hashFunction(int key) { + return key % TABLE_SIZE; +} + +// 在哈希表中插入键值对 +void insert(HashTable* hashTable, int key, int value) { + int index = hashFunction(key); + + Node* newNode = createNode(key, value); + + if (hashTable->table[index] == NULL) { + hashTable->table[index] = newNode; + } else { + Node* current = hashTable->table[index]; + while (current->next != NULL) { + current = current->next; + } + current->next = newNode; + } +} + +// 在哈希表中查找键是否存在 +int find(HashTable* hashTable, int key) { + int index = hashFunction(key); + + Node* current = hashTable->table[index]; + while (current != NULL) { + if (current->key == key) { + return 1; + } + current = current->next; + } + + return 0; // 未找到对应的值 +} + +// 在哈希表中查找键对应的值 +int get(HashTable* hashTable, int key) { + int index = hashFunction(key); + + Node* current = hashTable->table[index]; + while (current != NULL) { + if (current->key == key) { + return current->value; + } + current = current->next; + } + + return -1; // 未找到对应的值 +} + +int change(HashTable* hashTable, int key , int oldValue , int newValue) { + int index = hashFunction(key); + + Node* current = hashTable->table[index]; + while (current != NULL) { + if (current->key == key && current->value == oldValue) { + current->value = newValue; + return 1; + } + current = current->next; + } + + return 0; // 未找到对应的键值对 +} + +int deleteNode(HashTable* hashTable, int key , int value ) { + int index = hashFunction(key); + + Node* current = hashTable->table[index]; + Node* last = current; + if(current != NULL){ + if (current->key == key && current->value == value){ + hashTable->table[index] = current->next; + free(current); + return 1; + } + current = current->next; + } + + while (current != NULL) { + if (current->key == key && current->value == value) { + last->next=current->next; + free(current); + return 1; + } + last = current; + current = current->next; + + } + + return 0; // 未找到对应的键值对 +} + +void TestHash(void) +{ + HashTable* hashTable = createHashTable(); + printf("hashmap created\n"); + + // 在哈希表中插入键值对 + insert(hashTable, 3, 99); + printf("key-value pairs 3,99 inserted\n"); + insert(hashTable, 7, 88); + printf("key-value pairs 7,88 inserted\n"); + insert(hashTable, 13, 66); + printf("key-value pairs 13,66 inserted\n"); + insert(hashTable, 17, 55); + printf("key-value pairs 17,55 inserted\n"); + printf("\n"); + // 查找键对应的值 + + printf("find key 13 in created hashmap\n"); + if(find(hashTable, 13)){ + int value = get(hashTable, 13); + printf("Value: %d\n", value); // Output: 66 + } else { + printf("key not found\n"); + } + + + printf("find key 24 in created hashmap\n"); + if(find(hashTable, 24)){ + int value = get(hashTable, 24); + printf("Value: %d\n", value); + } else { + printf("key not found\n"); + } + printf("\n"); + + printf("key-value pairs 3,99 changed to 3,100\n"); + if(change(hashTable,3,99,100)){ + printf("success!value now: %d\n",get(hashTable,3)); + } else { + printf("fail!key-value pairs 3,99 not found\n"); + } + + printf("key-value pairs 2,99 changed to 2,100\n"); + if(change(hashTable,2,99,100)){ + printf("success!value: %d\n",get(hashTable,2)); + } else { + printf("fail!key-value pairs 2,99 not found\n"); + } + + printf("\n"); + if(deleteNode(hashTable,3,100)){ + printf("key-value pairs 3,100 deleted\n"); + } else { + printf("key-value pairs 3,100 not found\n"); + } + + find(hashTable,3) ? printf("key 3 : in hashmap\n") : printf("key 3 : not in hashmap\n"); + find(hashTable,13) ? printf("key 13 : in hashmap\n") : printf("key 13 : not in hashmap\n"); + printf("\n"); + // free hash map + free(hashTable->table); + free(hashTable); + printf("hashmap freed\n"); + return; + +} +PRIV_SHELL_CMD_FUNCTION(TestHash, a hash test sample, PRIV_SHELL_CMD_MAIN_ATTR); +#endif \ No newline at end of file diff --git a/APP_Framework/Applications/main.c b/APP_Framework/Applications/main.c index e1de024b5..ba56cb88f 100644 --- a/APP_Framework/Applications/main.c +++ b/APP_Framework/Applications/main.c @@ -20,7 +20,7 @@ extern int FrameworkInit(); extern void ApplicationOtaTaskInit(void); int main(void) { - printf("Hello, world! \n"); + printf("Hello, world! \n Running on stm32f407-st-discovery\n"); FrameworkInit(); #ifdef APPLICATION_OTA ApplicationOtaTaskInit();