From 780999cfe8b9a9eda60726fa0623512816096263 Mon Sep 17 00:00:00 2001 From: HenryWu <21307130040@m.fudan.edu.cn> Date: Thu, 22 Jun 2023 18:54:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=80=E7=BA=A7=E8=B5=9B=E9=A2=981?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APP_Framework/Applications/app_test/Kconfig | 3 + APP_Framework/Applications/app_test/Makefile | 4 + .../Applications/app_test/test_hash/README.md | 184 ++++++++++++++++++ .../app_test/test_hash/test_hash.c | 56 ++++++ .../app_test/test_hash/test_hash.h | 108 ++++++++++ 5 files changed, 355 insertions(+) create mode 100644 APP_Framework/Applications/app_test/test_hash/README.md create mode 100644 APP_Framework/Applications/app_test/test_hash/test_hash.c create mode 100644 APP_Framework/Applications/app_test/test_hash/test_hash.h diff --git a/APP_Framework/Applications/app_test/Kconfig b/APP_Framework/Applications/app_test/Kconfig index 45df5f5d5..9a6c7aa79 100644 --- a/APP_Framework/Applications/app_test/Kconfig +++ b/APP_Framework/Applications/app_test/Kconfig @@ -240,5 +240,8 @@ menu "test app" bool "Config test soft timer" default n + menuconfig USER_TEST_HASH + bool "Config test hash" + default n endif endmenu diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index 1cf919846..09ae5c0f1 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -101,5 +101,9 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),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..c0061ee3d --- /dev/null +++ b/APP_Framework/Applications/app_test/test_hash/README.md @@ -0,0 +1,184 @@ +# 热身赛一级赛题1:基于cortex-m3-emulator实现哈希表并测试验证 + +## 1. 简介 + +​ 用c语言实现哈希表数据结构,编译到cortex-m3-emulator的指令中,并且成功运行。 + +## 2. 数据结构设计说明 + +```c +//定义链表节点结构 +typedef struct Node { + int key; + int value; + struct Node* next; +} Node; +``` + +```c +//哈希表结构 +typedef struct HashTable { + Node* table[TABLE_SIZE]; +} HashTable; +``` + +```c +//创建新节点的函数,开辟一块内存空间,将key和value赋值并返回 +Node* createNode(int key, int value) { + Node* newNode = (Node*)malloc(sizeof(Node)); + newNode->key = key; + newNode->value = value; + newNode->next = NULL; + return newNode; +} +``` + +```c +//创建哈希表的函数,并为每个节点初始化 +HashTable* createHashTable() { + HashTable* newTable = (HashTable*)malloc(sizeof(HashTable)); + int i; + for (i = 0; i < TABLE_SIZE; i++) { + newTable->table[i] = NULL; + } + return newTable; +} +``` + +```c +//hash函数,这里简单地把key模TABLE_SIZE的值当做下标 +int hash(int key) { + return key % TABLE_SIZE; +} +``` + +```c +//在哈希表中插入键值对的函数 +void insert(HashTable* ht, int key, int value) { + int index = hash(key); + Node* newNode = createNode(key, value); + + // 如果该位置为空,则直接插入节点 + if (ht->table[index] == NULL) { + ht->table[index] = newNode; + } + else { + // 如果该位置已经有节点存在,则将新节点插入链表头部 + newNode->next = ht->table[index]; + ht->table[index] = newNode; + } +} +``` + +```c +// 根据键查找值 +int search(HashTable* ht, int key) { + int index = hash(key); + Node* currentNode = ht->table[index]; + + // 在链表中查找键 + while (currentNode != NULL) { + if (currentNode->key == key) { + return currentNode->value; + } + currentNode = currentNode->next; + } + + // 键未找到 + return -1; +} +``` + +```c +// 从哈希表中删除键值对 +void delete (HashTable* ht, int key) { + int index = hash(key); + Node* currentNode = ht->table[index]; + Node* prevNode = NULL; + + // 在链表中查找键 + while (currentNode != NULL && currentNode->key != key) { + prevNode = currentNode; + currentNode = currentNode->next; + } + + // 如果找到键,则删除节点 + if (currentNode != NULL) { + if (prevNode == NULL) { + ht->table[index] = currentNode->next; + } + else { + prevNode->next = currentNode->next; + } + free(currentNode); + } +} +``` + +```c +// 打印哈希表内容 +void printHashTable(HashTable* ht) { + int i; + for (i = 0; i < TABLE_SIZE; i++) { + printf("Bucket %d: ", i); + Node* currentNode = ht->table[i]; + while (currentNode != NULL) { + printf("(%d, %d) ", currentNode->key, currentNode->value); + currentNode = currentNode->next; + } + printf("\n"); + } +} +``` + +## 3. 测试程序说明 + +```c +// 测试函数 +void TestHash(void) { + HashTable* ht = createHashTable(); + + // 在哈希表中插入键值对 + insert(ht, 1, 10); + insert(ht, 2, 20); + insert(ht, 3, 30); + insert(ht, 11, 110); + insert(ht, 21, 210); + insert(ht, 4, 40); + + // 打印哈希表内容 + printHashTable(ht); + + // 根据键查找值 + int value = search(ht, 2); + printf("Value for key 2: %d\n", value); + + // 从哈希表中删除键值对 + delete (ht, 3); + delete (ht, 11); + + // 打印哈希表内容 + printHashTable(ht); + + // 释放哈希表内存 + free(ht); + return; +} +``` + +## 4. 运行结果(##需结合运行测试截图按步骤说明##) + +​ 成功编译以后在XiZi_IIoT目录下输入指令打开qemu + +![Imgur](https://i.imgur.com/IQCOOm4.png) + +输入Help指令,看到TestHash已经被成功编译为qemu指令 + +![Imgur](https://i.imgur.com/v16mC37.png) + +输入TestHash,输出结果如下,哈希表的各表项按照指令插入、查询和删除,hash表实现完毕。 + +![Imgur](https://i.imgur.com/fZAxGUo.png) + +​ + 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..00fa5394a --- /dev/null +++ b/APP_Framework/Applications/app_test/test_hash/test_hash.c @@ -0,0 +1,56 @@ +/* +* 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 +* @version: 1.1 +* @author: ROGEEK TEAM +* @date: 2023/6/20 +*/ +#include +#include +#include +#include "test_hash.h" +#ifdef ADD_XIZI_FETURES +// 测试函数 +void TestHash(void) { + HashTable* ht = createHashTable(); + + // 在哈希表中插入键值对 + insert(ht, 1, 10); + insert(ht, 2, 20); + insert(ht, 3, 30); + insert(ht, 11, 110); + insert(ht, 21, 210); + insert(ht, 4, 40); + + // 打印哈希表内容 + printHashTable(ht); + + // 根据键查找值 + int value = search(ht, 2); + printf("Value for key 2: %d\n", value); + + // 从哈希表中删除键值对 + delete (ht, 3); + delete (ht, 11); + + // 打印哈希表内容 + printHashTable(ht); + + // 释放哈希表内存 + free(ht); + return; +} +PRIV_SHELL_CMD_FUNCTION(TestHash, a dac test sample, PRIV_SHELL_CMD_MAIN_ATTR); +#endif \ 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 new file mode 100644 index 000000000..996951958 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_hash/test_hash.h @@ -0,0 +1,108 @@ +#define TABLE_SIZE 10 + +// 链表节点结构 +typedef struct Node { + int key; + int value; + struct Node* next; +} Node; + +// 哈希表结构 +typedef struct HashTable { + Node* table[TABLE_SIZE]; +} 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* newTable = (HashTable*)malloc(sizeof(HashTable)); + int i; + for (i = 0; i < TABLE_SIZE; i++) { + newTable->table[i] = NULL; + } + return newTable; +} + +// 哈希函数 +int hash(int key) { + return key % TABLE_SIZE; +} + +// 在哈希表中插入键值对 +void insert(HashTable* ht, int key, int value) { + int index = hash(key); + Node* newNode = createNode(key, value); + + // 如果该位置为空,则直接插入节点 + if (ht->table[index] == NULL) { + ht->table[index] = newNode; + } + else { + // 如果该位置已经有节点存在,则将新节点插入链表头部 + newNode->next = ht->table[index]; + ht->table[index] = newNode; + } +} + +// 根据键查找值 +int search(HashTable* ht, int key) { + int index = hash(key); + Node* currentNode = ht->table[index]; + + // 在链表中查找键 + while (currentNode != NULL) { + if (currentNode->key == key) { + return currentNode->value; + } + currentNode = currentNode->next; + } + + // 键未找到 + return -1; +} + +// 从哈希表中删除键值对 +void delete (HashTable* ht, int key) { + int index = hash(key); + Node* currentNode = ht->table[index]; + Node* prevNode = NULL; + + // 在链表中查找键 + while (currentNode != NULL && currentNode->key != key) { + prevNode = currentNode; + currentNode = currentNode->next; + } + + // 如果找到键,则删除节点 + if (currentNode != NULL) { + if (prevNode == NULL) { + ht->table[index] = currentNode->next; + } + else { + prevNode->next = currentNode->next; + } + free(currentNode); + } +} + +// 打印哈希表内容 +void printHashTable(HashTable* ht) { + int i; + for (i = 0; i < TABLE_SIZE; i++) { + printf("Bucket %d: ", i); + Node* currentNode = ht->table[i]; + while (currentNode != NULL) { + printf("(%d, %d) ", currentNode->key, currentNode->value); + currentNode = currentNode->next; + } + printf("\n"); + } +} \ No newline at end of file