From a03f6de225bd73634257b711495364fb804b85ad Mon Sep 17 00:00:00 2001 From: cwolf9 <2717232422@qq.com> Date: Mon, 5 Jun 2023 15:41:24 +0800 Subject: [PATCH] 2023_open_source_contest_warmup_1st_issue1 --- APP_Framework/Applications/app_test/Kconfig | 6 +- APP_Framework/Applications/app_test/Makefile | 4 + .../Applications/app_test/test_hash/README.md | 108 +++++++ .../app_test/test_hash/evaluation.png | Bin 0 -> 38514 bytes .../app_test/test_hash/test_hash.c | 265 ++++++++++++++++++ .../app_test/test_hash/test_hash.h | 13 + 6 files changed, 395 insertions(+), 1 deletion(-) create mode 100644 APP_Framework/Applications/app_test/test_hash/README.md create mode 100644 APP_Framework/Applications/app_test/test_hash/evaluation.png 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..d60f20208 100644 --- a/APP_Framework/Applications/app_test/Kconfig +++ b/APP_Framework/Applications/app_test/Kconfig @@ -1,9 +1,13 @@ menu "test app" menuconfig USER_TEST bool "Enable application test function " - default n + default y if USER_TEST + menuconfig USER_HASH_TABLE + bool "Config test hash table" + default y + menuconfig USER_TEST_ADC bool "Config test adc" default n diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index 1cf919846..90bcad1b2 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -25,6 +25,10 @@ endif ifeq ($(CONFIG_ADD_XIZI_FETURES),y) SRC_FILES := test_shell.c + ifeq ($(CONFIG_USER_HASH_TABLE),y) + SRC_FILES += test_hash/test_hash.c + endif + ifeq ($(CONFIG_USER_TEST_ADC),y) SRC_FILES += test_adc.c 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..805fdd122 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_hash/README.md @@ -0,0 +1,108 @@ + +# 热身赛一级赛题1:基于cortex-m3-emulator实现哈希表并测试验证 + +[toc] + +参赛战队:bdislab_0 +赛题issue:热身赛一级赛题1 +完成情况:实现哈希表,支持链地址法解决哈希冲突。 + +## 1. 简介:注册shell命令以及哈希命令集说明 +**0. 注册TestHashTable命令** +源文件见:APP_Framework/Applications/app_test/test_hash/test_hash.c + +**1. 插入(key, value)对** +``` +TestHashTable 1 key value +``` +说明: +- 当插入的key不存在时,返回 success。 +- 当插入的key已经存在时,新值value会覆盖旧值。 +- 注意:key支持`int`或`string`等若干类型数值,但value仅支持`int`范围内的数值。 + + +**2. 查询key对应的(key, value)对** +``` +TestHashTable 2 key value +``` +说明: +- 当查询的key存在时,输出对应的(key, value)对。 +- 当查询的key不存在时,返回 not exist。 + + +**3. 删除key对应的(key, value)对** +``` +TestHashTable 3 key value +``` +说明: +- 当删除的key存在时,删除对应的(key, value)对。 +- 当删除的key不存在时,返回 not exist。 + +**4. 执行帮助** +``` +TestHashTable help +``` +输出指令集帮助。 + +## 2. 数据结构设计说明 + +首先,设计了一个结构体 `struct Hash_entry` 表示每一项哈希结构,字段如下:包含原始的key变量(字符串类型的okey),哈希后的key变量(int类型的key),和value变量。 +``` +struct Hash_entry { + char *okey; + int key; + int val; + struct Hash_entry *next; + struct Hash_entry *prev; +}; +``` + +第二,哈希的模数为MOD。通过拉链法解决哈希冲突,所以定义了MOD个哈希链表的头,即`struct Hash_entry *hts[MOD]`。并定义了一个数组记录每种哈希值对应链表的长度,即`int htlen[MOD]`。 + +第三,获取哈希值的函数:`int get_hash_val(char *okey)`。 + +第四,插入:`int insert_kv(char *okey, char *val)`。 + +第五,查询:`int query_key(char *okey)`。 + +第六,删除:`int delete_key(char *okey)`。 + +## 3. 测试程序说明 + +测试结果,打印验证功能:均正确。 + +## 4. 运行结果:测试流程及截图 + +注意:key支持`int`或`string`等若干类型数值,但value仅支持`int`范围内的数值。 + +测试流程: +1. 首先查看哈希表指令集执行帮助:`TestHashTable help` +2. 插入(1, 1)对:`TestHashTable 1 1 1`,插入成功返回success +3. 重复插入(1, 2)对:`TestHashTable 1 1 2`,新值2覆盖旧值1 +4. 查询2对应的(key, value)对:`TestHashTable 2 2`,返回not exist +5. 查询1对应的(key, value)对:`TestHashTable 2 1`,输出key(1), value(2) +6. 删除1对应的(key, value)对:`TestHashTable 3 1`,删除成功返回success +7. 查询1对应的(key, value)对:`TestHashTable 2 1`,返回not exist +8. 插入(1, 10)对:`TestHashTable 1 1 10`,插入成功返回success +9. 查询1对应的(key, value)对:`TestHashTable 2 1`,输出key(1), value(10) + +测试截图: +![](evaluation.png) + +总结:注册shell命令,打印验证功能均正确。 + +## 附录 + +修改/新增的文件列表: +``` +APP_Framework/Applications/app_test/Kconfig +APP_Framework/Applications/app_test/Makefile +APP_Framework/Applications/app_test/test_hash/ +APP_Framework/Applications/app_test/test_hash/README.md +APP_Framework/Applications/app_test/test_hash/test_hash.c +APP_Framework/Applications/app_test/test_hash/evaluation.png +``` + +赛题链接: https://www.gitlink.org.cn/xuos/xiuos/issues/261 + +提交指南: https://www.gitlink.org.cn/competitions/index/track1_2023_xiuos diff --git a/APP_Framework/Applications/app_test/test_hash/evaluation.png b/APP_Framework/Applications/app_test/test_hash/evaluation.png new file mode 100644 index 0000000000000000000000000000000000000000..bd8c70eb579afc9b1a110cabd287565b65445214 GIT binary patch literal 38514 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 A9smFU literal 0 HcmV?d00001 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..70e467abe --- /dev/null +++ b/APP_Framework/Applications/app_test/test_hash/test_hash.c @@ -0,0 +1,265 @@ +/* +* 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: 2.0 +* @author: XiUOS Team: bdislab_0 +* @date: 2023/6/5 +*/ + +#include +#include +#include +#include +#include "test_hash.h" + +/** + * @brief Priv-shell Command definition + * + * @param _func Command function + * @param _desc Command description + * @param _attr Command attributes if need + */ +#define PRIV_SHELL_CMD_FUNCTION(_func, _desc, _attr) SHELL_EXPORT_CMD(_attr, _func, _func, _desc) + + +struct Hash_entry *create_hash_entry(char *okey_, int key_, int val_) { + return NULL; +} + +struct Hash_entry *hts[MOD]; +int htlen[MOD]; + +int get_hash_val(char *okey) { + int ans = 0; + while(*okey) { + ans = (ans * 233 + *okey) % MOD; + okey ++; + } + return ans; +} + +char * str_copy(char *s, char *t) { + int len = strlen(t) + 1; + s = (char *)malloc(len); + for(int i = 0; i < len; ++i) s[i] = t[i]; + s[len] = '\0'; + return s; +} + +void insert_tail(struct Hash_entry *head, struct Hash_entry *last, struct Hash_entry *tmp) { + last->next = tmp; + tmp->next = head; + tmp->prev = last; + head->prev = tmp; +} + +int str_to_int(char *str) { + int ans = 0; + while(*str) { + ans = (ans * 10 + *str - '0'); + str ++; + } + return ans; +} + +int insert_kv(char *okey, char *val) { + int key = get_hash_val(okey); + int ret = NOT_EXIST_VAL; + if(htlen[key] == 0) { + hts[key] = (struct Hash_entry *)malloc(sizeof(struct Hash_entry)); + hts[key]->prev = hts[key]; + hts[key]->next = hts[key]; + hts[key]->okey = str_copy(hts[key]->okey, okey); + hts[key]->key = key; + hts[key]->val = str_to_int(val); + // printf("insert_kv: %p %s %d %d\n", hts[key], hts[key]->okey, key, hts[key]->val); + htlen[key] += 1; + return ret; + }else { + struct Hash_entry *head = hts[key]; + if(strcmp(head->okey, okey) == 0) { + ret = head->val; + head->val = str_to_int(val); + }else { + head = head->next; + while(head != hts[key]) { + if(strcmp(head->okey, okey) == 0) { + ret = head->val; + head->val = str_to_int(val); + break; + } + head = head->next; + } + } + if(ret != NOT_EXIST_VAL) { + return ret; + } + struct Hash_entry *new_he = (struct Hash_entry *)malloc(sizeof(struct Hash_entry)); + new_he->prev = new_he; + new_he->next = new_he; + new_he->okey = str_copy(new_he->okey, okey); + new_he->key = key; + new_he->val = str_to_int(val); + insert_tail(hts[key], hts[key]->prev, new_he); + htlen[key] += 1; + return ret; + } +} + +int query_key(char *okey) { + int val = NOT_EXIST_VAL; + int key = get_hash_val(okey); + if(htlen[key] != 0) { + struct Hash_entry *head = hts[key]; + if(strcmp(head->okey, okey) == 0) { + val = head->val; + }else { + head = head->next; + while(head != hts[key]) { + if(strcmp(head->okey, okey) == 0) { + val = head->val; + break; + } + head = head->next; + } + } + } + return val; +} + +int delete_key(char *okey) { + int ret = NOT_EXIST_VAL; + int key = get_hash_val(okey); + if(htlen[key] != 0) { + struct Hash_entry *head = hts[key]; + if(strcmp(head->okey, okey) == 0) { + ret = head->val; + struct Hash_entry * le = head->prev, *ri = head->next; + le->next = ri; + ri->prev = le; + hts[key] = ri; + free(head->okey); + free(head); + htlen[key] -= 1; + }else { + head = head->next; + while(head != hts[key]) { + if(strcmp(head->okey, okey) == 0) { + ret = head->val; + struct Hash_entry * le = head->prev, *ri = head->next; + le->next = ri; + ri->prev = le; + // hts[key] = ri; + free(head->okey); + free(head); + htlen[key] -= 1; + break; + } + head = head->next; + } + } + } + return ret; +} + +void TestHashTable(int argc, char *argv[]) +{ + printf("%d parameter(s): ", argc); + for (char i = 1; i < argc; i++) { + printf("%s ", argv[i]); + } + printf("\r\n"); + if(argc == 4 && argv[1][0] == '1') {// x.c 1 key val + int val = insert_kv(argv[2], argv[3]); + if(val == NOT_EXIST_VAL) { + printf("insert key (%s), val (%s) success\n", argv[2], argv[3]); + }else { + printf("insert key (%s), val (%s) repeat, old value (%d) is overwritten\n", argv[2], argv[3], 1); + } + }else if(argc == 3 && argv[1][0] == '2') {// x.c 2 key + int val = query_key(argv[2]); + if(val == NOT_EXIST_VAL) { + printf("query key(%s), not exist\n", argv[2]); + }else { + printf("query key(%s), answer: %d\n", argv[2], val); + } + }else if(argc == 3 && argv[1][0] == '3') {// x.c 3 key + // del + int val = delete_key(argv[2]); + if(val == NOT_EXIST_VAL) { + printf("delete key(%s), not exist\n", argv[2]); + }else { + printf("delete key(%s), val(%d) success\n", argv[2], val); + } + }else if(argc == 2 && argv[1][0] == 'h') {// x.c help + // help + printf("TestHashTable help:\n"); + printf("- 1 key val: insert (key, val), duplicate keys will overwrite old values. Only `int` range data is supported\n"); + printf("- 2 key: query key\n"); + printf("- 3 key: delete key\n"); + printf("- help: help\n"); + } +} +PRIV_SHELL_CMD_FUNCTION(TestHashTable, a hashtable sample, PRIV_SHELL_CMD_MAIN_ATTR); + + +// int main() { +// int n; +// int opt; +// char key[55], val[55]; +// printf("input opertion numbers:\n"); +// scanf("%d", &n); +// while(n --) { +// printf("\ninput opertion:\n"); +// scanf("%d", &opt); +// if(opt == 1) { +// scanf("%s%s", key, val); +// int ret = insert_kv(key, val); +// printf("insert key: %s, val: %s, ret: %d\n", key, val, ret); +// }else if(opt == 2) { +// scanf("%s", key); +// int val = query_key(key); +// printf("query key: %s, answer: %d\n", key, val); +// }else if(opt == 3) { +// scanf("%s", key); +// int val = delete_key(key); +// printf("query key: %s, answer: %d\n", key, val); +// } +// else { +// printf("error opt\n"); +// break; +// } +// } +// return 0; +// } + +/* +gcc test_hash.c +./a.out +12 +1 10 10 +2 10 + + +1 1 1 +1 1 2 +2 2 +2 1 +3 1 +2 1 +1 1 10 +2 1 + +*/ \ 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..250f8c52c --- /dev/null +++ b/APP_Framework/Applications/app_test/test_hash/test_hash.h @@ -0,0 +1,13 @@ + +const int INF = 0x3f3f3f3f; + +#define MOD (1000 + 5) +#define NOT_EXIST_VAL (-INF) + +struct Hash_entry { + char *okey; + int key; + int val; + struct Hash_entry *next; + struct Hash_entry *prev; +};