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)
|
ifeq ($(CONFIG_USER_TEST_RBTREE),y)
|
||||||
SRC_FILES += test_rbtree/test_rbtree.c
|
SRC_FILES += test_rbtree/test_rbtree.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_USER_TEST_SOCKET),y)
|
ifeq ($(CONFIG_USER_TEST_SOCKET),y)
|
||||||
SRC_FILES += test_socket.c
|
SRC_FILES += test_socket.c
|
||||||
|
|
|
@ -9,13 +9,15 @@
|
||||||
基数树节点设计为:
|
基数树节点设计为:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
typedef struct _node {
|
typedef struct radix_node
|
||||||
void* value;
|
{
|
||||||
struct _node* next[NODE_SIZE];
|
void *value;
|
||||||
} node;
|
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 个函数,分别为:
|
一共实现了 5 个函数,分别为:
|
||||||
|
|
||||||
|
@ -32,20 +34,19 @@ typedef struct _node {
|
||||||
测试程序定义了以下键值对:
|
测试程序定义了以下键值对:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
char keys[][MAX_WORD_LEN] = {
|
char values[][16] = {
|
||||||
"what",
|
"what",
|
||||||
"where",
|
"where",
|
||||||
"why",
|
"why",
|
||||||
"how",
|
"how",
|
||||||
"hello!",
|
"hello!",
|
||||||
"apple",
|
"apple",
|
||||||
"12345"
|
"12345"};
|
||||||
};
|
unsigned int keys[] = {1, 2, 3, 4, 5, 6, 7};
|
||||||
int values[] = {1, 2, 3, 4, 5, 6, 7};
|
|
||||||
```
|
```
|
||||||
|
|
||||||
1. 程序的第一部分创建了基数树,并且将定义的 7 个键值对的前 6 个插入了基数树,然后分别查找 7 个键,前 6 个均可以找到对应的值,最后一个未插入,因此无法找到
|
1. 程序的第一部分创建了基数树,并且将定义的 7 个键值对的前 6 个插入了基数树,然后分别查找 7 个键,前 6 个均可以找到对应的值,最后一个未插入,因此无法找到
|
||||||
2. 程序的第二部分从基数树中删除了 `where` 和 `how` 两个键,再次分别查找 7 个键,删除的键值对和未插入的键值对均无法找到
|
2. 程序的第二部分从基数树中删除了 `where` 和 `how` 两个值的键,再次分别查找 7 个键,删除的键值对和未插入的键值对均无法找到
|
||||||
3. 程序的第三部分重新插入了已删除的 `where` 和未插入过的 `12345` ,再次分别查找 7 个键,新插入的值可以检索到
|
3. 程序的第三部分重新插入了已删除的 `where` 和未插入过的 `12345` ,再次分别查找 7 个键,新插入的值可以检索到
|
||||||
4. 程序的第四部分将基数树销毁,再次分别查找 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
|
* @file: test_radix_tree.c
|
||||||
* @brief: Implement a simple radix tree
|
* @brief: Implement a simple radix tree
|
||||||
* @version: 1.0
|
* @version: 1.0
|
||||||
* @date: 2023/5/24
|
* @date: 2023/5/24
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <transform.h>
|
|
||||||
#include "test_radix_tree.h"
|
#include "test_radix_tree.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: Create a radix tree node
|
* @description: Create a radix tree node
|
||||||
* @return node pointer
|
* @return node pointer
|
||||||
*/
|
*/
|
||||||
node* CreateNode()
|
radix_node *CreateNode()
|
||||||
{
|
{
|
||||||
node* n = (node*)malloc(sizeof(node));
|
radix_node *n = (radix_node *)malloc(sizeof(radix_node));
|
||||||
n->value = NULL;
|
if (n != NULL)
|
||||||
for (int i = 0; i < NODE_SIZE; i++) {
|
{
|
||||||
n->next[i] = NULL;
|
n->parent = NULL;
|
||||||
|
n->value = NULL;
|
||||||
|
for (int i = 0; i < NODE_SIZE; ++i)
|
||||||
|
{
|
||||||
|
n->child[i] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
@ -29,21 +33,32 @@ node* CreateNode()
|
||||||
* @param value - new node value
|
* @param value - new node value
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
void InsertNode(node* root, const char* key, void* value)
|
int InsertNode(radix_node *root, unsigned int key, void *value)
|
||||||
{
|
{
|
||||||
if (root == NULL) {
|
if (root == NULL)
|
||||||
return;
|
{
|
||||||
|
return -1; // The root node is empty
|
||||||
}
|
}
|
||||||
node* cur = root;
|
radix_node *cur = root;
|
||||||
size_t len = strlen(key);
|
int temp;
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (int i = radix_tree_height - 1; i >= 0; --i)
|
||||||
uint8_t b = (uint8_t)key[i];
|
{
|
||||||
if (cur->next[b] == NULL) {
|
temp = CHECK_BITS(key, i);
|
||||||
cur->next[b] = CreateNode();
|
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;
|
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
|
* @param key - key which is needed to delete
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
void DeleteNode(node* root, const char* key)
|
void DeleteNode(radix_node *root, unsigned int key)
|
||||||
{
|
{
|
||||||
if (root == NULL) {
|
if (root == NULL)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
node** cur = &root;
|
radix_node *cur = root;
|
||||||
size_t len = strlen(key);
|
int temp;
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (int i = radix_tree_height - 1; i >= 0; --i)
|
||||||
uint8_t b = (uint8_t)key[i];
|
{
|
||||||
if ((*cur)->next[b] == NULL) {
|
temp = CHECK_BITS(key, i);
|
||||||
return;
|
cur = cur->child[temp];
|
||||||
}
|
if (!cur)
|
||||||
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;
|
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
|
* @param key - key which is needed to find
|
||||||
* @return value pointer corresponding to key
|
* @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;
|
return NULL;
|
||||||
}
|
}
|
||||||
node* cur = root;
|
radix_node *cur = root;
|
||||||
size_t len = strlen(key);
|
int temp;
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (int i = radix_tree_height - 1; i >= 0; --i)
|
||||||
uint8_t b = (uint8_t)key[i];
|
{
|
||||||
if (cur->next[b] == NULL) {
|
temp = CHECK_BITS(key, i);
|
||||||
return NULL;
|
cur = cur->child[temp];
|
||||||
}
|
if (!cur)
|
||||||
cur = cur->next[b];
|
break;
|
||||||
}
|
}
|
||||||
|
if (!cur)
|
||||||
|
return NULL;
|
||||||
return cur->value;
|
return cur->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,73 +121,88 @@ void* FindNode(node* root, const char* key)
|
||||||
* @param root - radix tree root
|
* @param root - radix tree root
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
void DestroyTree(node* root)
|
void DestroyTree(radix_node *root)
|
||||||
{
|
{
|
||||||
if (root == NULL) {
|
if (root == NULL)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < NODE_SIZE; i++) {
|
for (int i = 0; i < NODE_SIZE; i++)
|
||||||
DestroyTree(root->next[i]);
|
{
|
||||||
|
DestroyTree(root->child[i]);
|
||||||
}
|
}
|
||||||
free(root);
|
free(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestRadix()
|
void TestRadix()
|
||||||
{
|
{
|
||||||
char keys[][MAX_WORD_LEN] = {
|
char values[][16] = {
|
||||||
"what",
|
"what",
|
||||||
"where",
|
"where",
|
||||||
"why",
|
"why",
|
||||||
"how",
|
"how",
|
||||||
"hello!",
|
"hello!",
|
||||||
"apple",
|
"apple",
|
||||||
"12345"
|
"12345"};
|
||||||
};
|
unsigned int keys[] = {1, 2, 3, 4, 5, 6, 7};
|
||||||
int values[] = {1, 2, 3, 4, 5, 6, 7};
|
|
||||||
|
|
||||||
printf("\nCreate tree and add key & value:\n");
|
printf("\nCreate tree and add key & value:\n");
|
||||||
node* root = CreateNode();
|
radix_node *root = CreateNode();
|
||||||
if (!root) printf("Create node failed.\n");
|
if (!root)
|
||||||
|
printf("Create node failed.\n");
|
||||||
|
|
||||||
int num = sizeof(keys) / sizeof(keys[0]);
|
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]);
|
InsertNode(root, keys[i], &values[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < num; ++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]);
|
char *v = (char *)FindNode(root, keys[i]);
|
||||||
else printf("keys[%d] \"%s\" not found\n", i, 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");
|
printf("\nDelete \"where\" and \"how\":\n");
|
||||||
DeleteNode(root, keys[1]);
|
DeleteNode(root, keys[1]);
|
||||||
DeleteNode(root, keys[3]);
|
DeleteNode(root, keys[3]);
|
||||||
|
|
||||||
for (int i = 0; i < num; ++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]);
|
char *v = (char *)FindNode(root, keys[i]);
|
||||||
else printf("keys[%d] \"%s\" not found\n", i, 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");
|
printf("\nInsert \"where\" and \"12345\":\n");
|
||||||
InsertNode(root, keys[1], &values[1]);
|
InsertNode(root, keys[1], &values[1]);
|
||||||
InsertNode(root, keys[6], &values[6]);
|
InsertNode(root, keys[6], &values[6]);
|
||||||
|
|
||||||
for (int i = 0; i < num; ++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]);
|
char *v = (char *)FindNode(root, keys[i]);
|
||||||
else printf("keys[%d] \"%s\" not found\n", i, 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");
|
printf("\nDestroy tree:\n");
|
||||||
DestroyTree(root);
|
DestroyTree(root);
|
||||||
root = NULL;
|
root = NULL;
|
||||||
|
|
||||||
for (int i = 0; i < num; ++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]);
|
char *v = (char *)FindNode(root, keys[i]);
|
||||||
else printf("keys[%d] \"%s\" not found\n", i, 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
|
* @file: test_radix_tree.h
|
||||||
* @brief: Implement a simple radix tree
|
* @brief: Implement a simple radix tree
|
||||||
* @version: 1.0
|
* @version: 1.0
|
||||||
* @date: 2023/5/24
|
* @date: 2023/5/24
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define NODE_SIZE 128
|
#include <transform.h>
|
||||||
#define MAX_WORD_LEN 128
|
|
||||||
|
|
||||||
typedef struct _node {
|
#define NODE_SIZE 4
|
||||||
void* value;
|
#define BITS 2
|
||||||
struct _node* next[NODE_SIZE];
|
#define CHECK_BITS(key, pos) ((((unsigned int)(key)) << (sizeof(int) * 8 - (pos + 1) * BITS)) >> (sizeof(int) * 8 - BITS))
|
||||||
} node;
|
|
||||||
|
|
||||||
node* CreateNode();
|
const int radix_tree_height = sizeof(void *) * 8 / BITS; // Height of tree
|
||||||
void InsertNode(node* root, const char* key, void* value);
|
|
||||||
void DeleteNode(node* root, const char* key);
|
typedef struct radix_node
|
||||||
void* FindNode(node* root, const char* key);
|
{
|
||||||
void DestroyTree(node* root);
|
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