Commit 热身赛一级赛题3

This commit is contained in:
JasenChao 2023-05-24 16:39:32 +08:00
parent 7754a149a9
commit 832ebbfaec
11 changed files with 265 additions and 0 deletions

View File

@ -240,5 +240,9 @@ menu "test app"
bool "Config test soft timer"
default n
menuconfig USER_TEST_RADIX
bool "Config test radix tree"
default n
endif
endmenu

View File

@ -99,6 +99,10 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
ifeq ($(CONFIG_USER_TEST_TIMER),y)
SRC_FILES += test_timer.c
endif
ifeq ($(CONFIG_USER_TEST_RADIX),y)
SRC_FILES += test_radix_tree/test_radix_tree.c
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,63 @@
# 基数树
## 代码实现
基数树节点设计为:
```C
typedef struct _node {
void* value;
struct _node* next[NODE_SIZE];
} node;
```
其中,`NODE_SIZE` 定义为 128足以容纳所有 ASCII 值。
一共实现了 5 个函数,分别为:
- `CreateNode`:创建一个基数树节点
- `InsertNode`:将一对键值对插入基数树
- `DeleteNode`:删除指定键的键值对
- `FindNode`:查找指定键对应的值
- `DestroyTree`:销毁整个基数树
## 程序测试
测试程序 `TestRadix` 已经注册为 shell 命令,可以调用执行。
测试程序定义了以下键值对:
```c
char keys[][MAX_WORD_LEN] = {
"what",
"where",
"why",
"how",
"hello!",
"apple",
"12345"
};
int values[] = {1, 2, 3, 4, 5, 6, 7};
```
1. 程序的第一部分创建了基数树,并且将定义的 7 个键值对的前 6 个插入了基数树,然后分别查找 7 个键,前 6 个均可以找到对应的值,最后一个未插入,因此无法找到
2. 程序的第二部分从基数树中删除了 `where``how` 两个键,再次分别查找 7 个键,删除的键值对和未插入的键值对均无法找到
3. 程序的第三部分重新插入了已删除的 `where` 和未插入过的 `12345` ,再次分别查找 7 个键,新插入的值可以检索到
4. 程序的第四部分将基数树销毁,再次分别查找 7 个键,所有的键值对均无法找到
## 流程记录
1. 在工作区终端中输入命令:`make BOARD=k210-emulator menuconfig`,进入配置页面
![fig1](fig1.png)
2. 依次进入 `APP_Framework` -> `Applications` -> `test app` 目录,将 `Enable application test function` 选项置为 `Y`
![fig2](fig2.png)
3. 进入 `Enable application test function``Config test radix tree` 选项置为 `Y`
![fig3](fig3.png)
4. 一直选择 `Exit` 退出配置,在最后需要确认的页面选择 `Yes` 保存配置
![fig4](fig4.png)
5. 执行编译命令:`make BOARD=k210-emulator`,正常情况下应当编译无误
![fig5](fig5.png)
6. 在 `qemu` 中运行:`qemu-system-riscv64 -nographic -machine sifive_u -bios build/XiZi-k210-emulator.elf`
![fig6](fig6.png)
7. 在 shell 中运行命令 `TestRadix`,执行结果与预期一致,验证完成。
![fig7](fig7.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

View File

@ -0,0 +1,194 @@
/**
* @file: test_radix_tree.c
* @brief: Implement a simple radix tree
* @version: 1.0
* @date: 2023/5/24
*/
#include <transform.h>
#define NODE_SIZE 128
#define MAX_WORD_LEN 128
typedef struct _node {
void* value;
struct _node* next[NODE_SIZE];
} node;
/**
* @description: Create a radix tree node
* @return node pointer
*/
node* CreateNode()
{
node* n = (node*)malloc(sizeof(node));
n->value = NULL;
for (int i = 0; i < NODE_SIZE; i++) {
n->next[i] = NULL;
}
return n;
}
/**
* @description: Insert a new node to radix tree
* @param root - radix tree root
* @param key - new node key
* @param value - new node value
* @return void
*/
void InsertNode(node* root, const char* key, void* value)
{
if (root == NULL) {
return;
}
node* cur = root;
size_t len = strlen(key);
for (size_t i = 0; i < len; i++) {
uint8_t b = (uint8_t)key[i];
if (cur->next[b] == NULL) {
cur->next[b] = CreateNode();
}
cur = cur->next[b];
}
cur->value = value;
}
/**
* @description: Delete a node from radix tree
* @param root - radix tree root
* @param key - key which is needed to delete
* @return void
*/
void DeleteNode(node* root, const char* key)
{
if (root == NULL) {
return;
}
node** cur = &root;
size_t len = strlen(key);
for (size_t i = 0; i < len; i++) {
uint8_t b = (uint8_t)key[i];
if ((*cur)->next[b] == NULL) {
return;
}
cur = &((*cur)->next[b]);
}
if ((*cur)->value == NULL) {
return;
}
(*cur)->value = NULL;
int has_children = 0;
for (int i = 0; i < NODE_SIZE; i++) {
if ((*cur)->next[i] != NULL) {
has_children = 1;
break;
}
}
if (!has_children) {
free(*cur);
(*cur) = NULL;
}
}
/**
* @description: find a node by key
* @param root - radix tree root
* @param key - key which is needed to find
* @return value pointer corresponding to key
*/
void* FindNode(node* root, const char* key)
{
if (root == NULL) {
return NULL;
}
node* cur = root;
size_t len = strlen(key);
for (size_t i = 0; i < len; i++) {
uint8_t b = (uint8_t)key[i];
if (cur->next[b] == NULL) {
return NULL;
}
cur = cur->next[b];
}
return cur->value;
}
/**
* @description: Destroy the radix tree
* @param root - radix tree root
* @return void
*/
void DestroyTree(node* root)
{
if (root == NULL) {
return;
}
for (int i = 0; i < NODE_SIZE; i++) {
DestroyTree(root->next[i]);
}
free(root);
}
void TestRadix()
{
char keys[][MAX_WORD_LEN] = {
"what",
"where",
"why",
"how",
"hello!",
"apple",
"12345"
};
int values[] = {1, 2, 3, 4, 5, 6, 7};
printf("\nCreate tree and add key & value:\n");
node* root = CreateNode();
if (!root) printf("Create node failed.\n");
int num = sizeof(keys) / sizeof(keys[0]);
for (int i = 0; i < num - 1; ++i) {
InsertNode(root, keys[i], &values[i]);
}
for (int i = 0; i < num; ++i) {
int* v = (int*)FindNode(root, keys[i]);
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
}
printf("\nDelete \"where\" and \"how\":\n");
DeleteNode(root, keys[1]);
DeleteNode(root, keys[3]);
for (int i = 0; i < num; ++i) {
int* v = (int*)FindNode(root, keys[i]);
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
}
printf("\nInsert \"where\" and \"12345\":\n");
InsertNode(root, keys[1], &values[1]);
InsertNode(root, keys[6], &values[6]);
for (int i = 0; i < num; ++i) {
int* v = (int*)FindNode(root, keys[i]);
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
}
printf("\nDestroy tree:\n");
DestroyTree(root);
root = NULL;
for (int i = 0; i < num; ++i) {
int* v = (int*)FindNode(root, keys[i]);
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
}
}
PRIV_SHELL_CMD_FUNCTION(TestRadix, Implement a simple radix tree, PRIV_SHELL_CMD_MAIN_ATTR);