forked from xuos/xiuos
Merge branch '2023_open_source_contest' of https://gitlink.org.cn/JasenChao/xiuos into 2023_open_source_contest
This commit is contained in:
commit
deb1f63d9e
|
@ -115,7 +115,7 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
|||
|
||||
ifeq ($(CONFIG_USER_TEST_RBTREE),y)
|
||||
SRC_FILES += test_rbtree/test_rbtree.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USER_TEST_SOCKET),y)
|
||||
SRC_FILES += test_socket.c
|
||||
|
|
|
@ -9,13 +9,15 @@
|
|||
基数树节点设计为:
|
||||
|
||||
```c
|
||||
typedef struct _node {
|
||||
void* value;
|
||||
struct _node* next[NODE_SIZE];
|
||||
} node;
|
||||
typedef struct radix_node
|
||||
{
|
||||
void *value;
|
||||
struct radix_node *child[NODE_SIZE];
|
||||
struct radix_node *parent;
|
||||
} radix_node;
|
||||
```
|
||||
|
||||
其中,节点在树中的路径即为键,`value` 存储值,`NODE_SIZE` 定义为 128,足以容纳所有 ASCII 值。
|
||||
其中,节点在树中的路径即为键,为`unsigned int`类型,`value` 存储值,`NODE_SIZE` 定义为 4,即每个树节点包含2个bit位,可以根据实际需求调整。
|
||||
|
||||
一共实现了 5 个函数,分别为:
|
||||
|
||||
|
@ -32,20 +34,19 @@ typedef struct _node {
|
|||
测试程序定义了以下键值对:
|
||||
|
||||
```c
|
||||
char keys[][MAX_WORD_LEN] = {
|
||||
char values[][16] = {
|
||||
"what",
|
||||
"where",
|
||||
"why",
|
||||
"how",
|
||||
"hello!",
|
||||
"apple",
|
||||
"12345"
|
||||
};
|
||||
int values[] = {1, 2, 3, 4, 5, 6, 7};
|
||||
"12345"};
|
||||
unsigned int keys[] = {1, 2, 3, 4, 5, 6, 7};
|
||||
```
|
||||
|
||||
1. 程序的第一部分创建了基数树,并且将定义的 7 个键值对的前 6 个插入了基数树,然后分别查找 7 个键,前 6 个均可以找到对应的值,最后一个未插入,因此无法找到
|
||||
2. 程序的第二部分从基数树中删除了 `where` 和 `how` 两个键,再次分别查找 7 个键,删除的键值对和未插入的键值对均无法找到
|
||||
2. 程序的第二部分从基数树中删除了 `where` 和 `how` 两个值的键,再次分别查找 7 个键,删除的键值对和未插入的键值对均无法找到
|
||||
3. 程序的第三部分重新插入了已删除的 `where` 和未插入过的 `12345` ,再次分别查找 7 个键,新插入的值可以检索到
|
||||
4. 程序的第四部分将基数树销毁,再次分别查找 7 个键,所有的键值对均无法找到
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 91 KiB |
Binary file not shown.
Before Width: | Height: | Size: 238 KiB After Width: | Height: | Size: 96 KiB |
|
@ -1,23 +1,27 @@
|
|||
/**
|
||||
* @file: test_radix_tree.c
|
||||
* @brief: Implement a simple radix tree
|
||||
* @version: 1.0
|
||||
* @date: 2023/5/24
|
||||
*/
|
||||
* @file: test_radix_tree.c
|
||||
* @brief: Implement a simple radix tree
|
||||
* @version: 1.0
|
||||
* @date: 2023/5/24
|
||||
*/
|
||||
|
||||
#include <transform.h>
|
||||
#include "test_radix_tree.h"
|
||||
|
||||
/**
|
||||
* @description: Create a radix tree node
|
||||
* @return node pointer
|
||||
*/
|
||||
node* CreateNode()
|
||||
radix_node *CreateNode()
|
||||
{
|
||||
node* n = (node*)malloc(sizeof(node));
|
||||
n->value = NULL;
|
||||
for (int i = 0; i < NODE_SIZE; i++) {
|
||||
n->next[i] = NULL;
|
||||
radix_node *n = (radix_node *)malloc(sizeof(radix_node));
|
||||
if (n != NULL)
|
||||
{
|
||||
n->parent = NULL;
|
||||
n->value = NULL;
|
||||
for (int i = 0; i < NODE_SIZE; ++i)
|
||||
{
|
||||
n->child[i] = NULL;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
@ -29,21 +33,32 @@ node* CreateNode()
|
|||
* @param value - new node value
|
||||
* @return void
|
||||
*/
|
||||
void InsertNode(node* root, const char* key, void* value)
|
||||
int InsertNode(radix_node *root, unsigned int key, void *value)
|
||||
{
|
||||
if (root == NULL) {
|
||||
return;
|
||||
if (root == NULL)
|
||||
{
|
||||
return -1; // The root node is empty
|
||||
}
|
||||
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();
|
||||
radix_node *cur = root;
|
||||
int temp;
|
||||
for (int i = radix_tree_height - 1; i >= 0; --i)
|
||||
{
|
||||
temp = CHECK_BITS(key, i);
|
||||
if (!cur->child[temp])
|
||||
{
|
||||
cur->child[temp] = CreateNode();
|
||||
if (!cur->child[temp])
|
||||
return -2; // Failed to apply for a node
|
||||
cur->child[temp]->parent = cur;
|
||||
}
|
||||
cur = cur->next[b];
|
||||
cur = cur->child[temp];
|
||||
}
|
||||
if (cur->value == value)
|
||||
return -3; // Repeat insertion
|
||||
if (cur->value != NULL)
|
||||
return -4; // Already occupied
|
||||
cur->value = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,38 +67,27 @@ void InsertNode(node* root, const char* key, void* value)
|
|||
* @param key - key which is needed to delete
|
||||
* @return void
|
||||
*/
|
||||
void DeleteNode(node* root, const char* key)
|
||||
void DeleteNode(radix_node *root, unsigned int key)
|
||||
{
|
||||
if (root == NULL) {
|
||||
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;
|
||||
radix_node *cur = root;
|
||||
int temp;
|
||||
for (int i = radix_tree_height - 1; i >= 0; --i)
|
||||
{
|
||||
temp = CHECK_BITS(key, i);
|
||||
cur = cur->child[temp];
|
||||
if (!cur)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_children) {
|
||||
free(*cur);
|
||||
(*cur) = NULL;
|
||||
}
|
||||
|
||||
if (!cur)
|
||||
return;
|
||||
|
||||
cur->parent->child[temp] = NULL;
|
||||
free(cur);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,20 +96,23 @@ void DeleteNode(node* root, const char* key)
|
|||
* @param key - key which is needed to find
|
||||
* @return value pointer corresponding to key
|
||||
*/
|
||||
void* FindNode(node* root, const char* key)
|
||||
void *FindNode(radix_node *root, unsigned int key)
|
||||
{
|
||||
if (root == NULL) {
|
||||
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];
|
||||
radix_node *cur = root;
|
||||
int temp;
|
||||
for (int i = radix_tree_height - 1; i >= 0; --i)
|
||||
{
|
||||
temp = CHECK_BITS(key, i);
|
||||
cur = cur->child[temp];
|
||||
if (!cur)
|
||||
break;
|
||||
}
|
||||
if (!cur)
|
||||
return NULL;
|
||||
return cur->value;
|
||||
}
|
||||
|
||||
|
@ -114,73 +121,88 @@ void* FindNode(node* root, const char* key)
|
|||
* @param root - radix tree root
|
||||
* @return void
|
||||
*/
|
||||
void DestroyTree(node* root)
|
||||
void DestroyTree(radix_node *root)
|
||||
{
|
||||
if (root == NULL) {
|
||||
if (root == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < NODE_SIZE; i++) {
|
||||
DestroyTree(root->next[i]);
|
||||
for (int i = 0; i < NODE_SIZE; i++)
|
||||
{
|
||||
DestroyTree(root->child[i]);
|
||||
}
|
||||
free(root);
|
||||
}
|
||||
|
||||
void TestRadix()
|
||||
{
|
||||
char keys[][MAX_WORD_LEN] = {
|
||||
char values[][16] = {
|
||||
"what",
|
||||
"where",
|
||||
"why",
|
||||
"how",
|
||||
"hello!",
|
||||
"apple",
|
||||
"12345"
|
||||
};
|
||||
int values[] = {1, 2, 3, 4, 5, 6, 7};
|
||||
"12345"};
|
||||
unsigned int keys[] = {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");
|
||||
radix_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) {
|
||||
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]);
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
char *v = (char *)FindNode(root, keys[i]);
|
||||
if (v)
|
||||
printf("keys[%d] %x, values[%d] = %s\n", i, keys[i], i, v);
|
||||
else
|
||||
printf("keys[%d] %x 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]);
|
||||
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
char *v = (char *)FindNode(root, keys[i]);
|
||||
if (v)
|
||||
printf("keys[%d] %x, values[%d] = %s\n", i, keys[i], i, v);
|
||||
else
|
||||
printf("keys[%d] %x 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]);
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
char *v = (char *)FindNode(root, keys[i]);
|
||||
if (v)
|
||||
printf("keys[%d] %x, values[%d] = %s\n", i, keys[i], i, v);
|
||||
else
|
||||
printf("keys[%d] %x 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]);
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
char *v = (char *)FindNode(root, keys[i]);
|
||||
if (v)
|
||||
printf("keys[%d] %x, values[%d] = %s\n", i, keys[i], i, v);
|
||||
else
|
||||
printf("keys[%d] %x not found\n", i, keys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,27 @@
|
|||
/**
|
||||
* @file: test_radix_tree.h
|
||||
* @brief: Implement a simple radix tree
|
||||
* @version: 1.0
|
||||
* @date: 2023/5/24
|
||||
*/
|
||||
* @file: test_radix_tree.h
|
||||
* @brief: Implement a simple radix tree
|
||||
* @version: 1.0
|
||||
* @date: 2023/5/24
|
||||
*/
|
||||
|
||||
#define NODE_SIZE 128
|
||||
#define MAX_WORD_LEN 128
|
||||
#include <transform.h>
|
||||
|
||||
typedef struct _node {
|
||||
void* value;
|
||||
struct _node* next[NODE_SIZE];
|
||||
} node;
|
||||
#define NODE_SIZE 4
|
||||
#define BITS 2
|
||||
#define CHECK_BITS(key, pos) ((((unsigned int)(key)) << (sizeof(int) * 8 - (pos + 1) * BITS)) >> (sizeof(int) * 8 - BITS))
|
||||
|
||||
node* CreateNode();
|
||||
void InsertNode(node* root, const char* key, void* value);
|
||||
void DeleteNode(node* root, const char* key);
|
||||
void* FindNode(node* root, const char* key);
|
||||
void DestroyTree(node* root);
|
||||
const int radix_tree_height = sizeof(void *) * 8 / BITS; // Height of tree
|
||||
|
||||
typedef struct radix_node
|
||||
{
|
||||
void *value;
|
||||
struct radix_node *child[NODE_SIZE];
|
||||
struct radix_node *parent;
|
||||
} radix_node;
|
||||
|
||||
radix_node *CreateNode();
|
||||
int InsertNode(radix_node *root, unsigned int key, void *value);
|
||||
void DeleteNode(radix_node *root, unsigned int key);
|
||||
void *FindNode(radix_node *root, unsigned int key);
|
||||
void DestroyTree(radix_node *root);
|
Loading…
Reference in New Issue