diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index 36a913ca6..35752e630 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -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 diff --git a/APP_Framework/Applications/app_test/test_radix_tree/README.md b/APP_Framework/Applications/app_test/test_radix_tree/README.md index b2bfe9cb9..fb4efcb6f 100644 --- a/APP_Framework/Applications/app_test/test_radix_tree/README.md +++ b/APP_Framework/Applications/app_test/test_radix_tree/README.md @@ -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 个键,所有的键值对均无法找到 diff --git a/APP_Framework/Applications/app_test/test_radix_tree/fig6.png b/APP_Framework/Applications/app_test/test_radix_tree/fig6.png index 80bf28136..a8f0ab9c0 100644 Binary files a/APP_Framework/Applications/app_test/test_radix_tree/fig6.png and b/APP_Framework/Applications/app_test/test_radix_tree/fig6.png differ diff --git a/APP_Framework/Applications/app_test/test_radix_tree/fig7.png b/APP_Framework/Applications/app_test/test_radix_tree/fig7.png index 7fad83c9e..4b1073ba4 100644 Binary files a/APP_Framework/Applications/app_test/test_radix_tree/fig7.png and b/APP_Framework/Applications/app_test/test_radix_tree/fig7.png differ diff --git a/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.c b/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.c index c54a49805..a2c96e15e 100644 --- a/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.c +++ b/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.c @@ -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 #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]); } } diff --git a/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.h b/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.h index ea9e7b7fa..cef53561f 100644 --- a/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.h +++ b/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.h @@ -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 -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); \ No newline at end of file +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); \ No newline at end of file