diff --git a/APP_Framework/Applications/app_test/test_rbtree/README.md b/APP_Framework/Applications/app_test/test_rbtree/README.md index e69de29bb..b1e62b189 100644 --- a/APP_Framework/Applications/app_test/test_rbtree/README.md +++ b/APP_Framework/Applications/app_test/test_rbtree/README.md @@ -0,0 +1,95 @@ +# 热身赛一级赛题2:基于cortex-m4-emulator实现红黑树并测试验证 + +## 1. 简介 +基于矽璓模拟器cortex-m4-emulator,实现了红黑树基本数据结构和功能,主要包括查找、删除、插入、左旋、右旋等功能,并编写测试程序在shell终端打印结果 + + +## 2. 数据结构设计说明 +红黑树数据结构如下: +``` c +enum Type {RED,BLACK}; + +struct Node +{ + int data; + struct Node* left; + struct Node* right; + struct Node* parent; + enum Type color; +}; +``` +红黑树的每个节点上都有存储位表示节点的颜色,颜色是红(Red)或黑(Black)。 +红黑树的基本操作是添加、删除和旋转。在对红黑树进行添加或删除后,会用到旋转方法。旋转的目的是让树保持红黑树的特性。 + + +## 3. 测试程序说明 + 测试程序示例如下: + ```c + void TestRbtree(void) +{ + struct Node* RBT = NULL; //创建红黑树根节点 + + RBT = RbInsert(RBT,2); //插入节点 + RBT = RbInsert(RBT,1); + RBT = RbInsert(RBT,4); + RBT = RbInsert(RBT,5); + RBT = RbInsert(RBT,9); + RBT = RbInsert(RBT,3); + RBT = RbInsert(RBT,6); + RBT = RbInsert(RBT,7); + + printf("\nPreOrder - "); + PreOrder(RBT); //先序遍历 + + printf("\nLevel order - "); + LevelOrder(RBT); //层序遍历 + + struct Node* x = BstSearch(RBT,5); //查找 + RBT = RbDelete(RBT,x); //删除 + + + printf("\nAfter deleting 5"); + + printf("\nPreOrder - "); + PreOrder(RBT); + + front = NULL; rear = NULL; // Delete old Queue + + printf("\nLevel order - "); + LevelOrder(RBT); + +} + +PRIV_SHELL_CMD_FUNCTION(TestRbtree, a red black sample , PRIV_SHELL_CMD_MAIN_ATTR); //注册TestRbtree指令 + ``` +测试程序通过shell指令`TestRbtree`运行,之后输出红黑树插入系列节点后的先序遍历和层序遍历结果,之后删除查找到的节点,并观察结果是否正确。测试覆盖红黑树的插入、删除、查找、先序遍历、层序遍历等功能。 + + + + +## 4. 运行结果 + +运行系统`qemu-system-arm -machine netduinoplus2 -nographic -kernel build/XiZi-cortex-m4-emulator.elf`,之后通过`TestRbtree`指令运行测试程序,执行结果如下: + + ![执行结果](./img/result.png) + + 结果分析如下所示: + ### 1. 插入节点、层序遍历、先序遍历功能测试 + 1. 通过调用`RbInsert(RBT,val)`方法插入数据,初始数据为(2,1,4,5,9,3,6,7),其对应红黑树为: + ![初始生成的红黑树](img/rbtree.png) + 2. 首先调用`PreOrder`函数查看先序遍历结果为: + PreOrder - 2 1 5 4 3 7 6 9 + 与预期一致 + 3. 再调用`LevelOrder`方法,查看层级遍历结果为: + Level order - 2 1 5 4 7 3 6 9 + 与预期结果一致 + 由层序遍历和先序遍历结果,可以看出生成的红黑树和预期一致,插入操作正确。 + ### 2. 删除节点,查找节点功能测试 + 1. 首先通过`struct Node* x = BstSearch(RBT,5);`找到5对应的节点 + 2. 之后使用`RBT = RbDelete(RBT,x);`删除该节点,此时红黑树删除变化为: + ![删除元素5](img/delete5.png) + 3. 同测试1步骤2和3,我们通过`PreOrder`和`LevelOrder`查看此时的树为: + PreOrder - 2 1 6 4 3 7 9 + + Level order - 2 1 6 4 7 3 9 + 4. 运行结果与预期一致,红黑树的删除操作正确。 \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_rbtree/img/delete5.png b/APP_Framework/Applications/app_test/test_rbtree/img/delete5.png new file mode 100644 index 000000000..6c095aa99 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_rbtree/img/delete5.png differ diff --git a/APP_Framework/Applications/app_test/test_rbtree/img/rbtree.png b/APP_Framework/Applications/app_test/test_rbtree/img/rbtree.png new file mode 100644 index 000000000..25d884bcd Binary files /dev/null and b/APP_Framework/Applications/app_test/test_rbtree/img/rbtree.png differ diff --git a/APP_Framework/Applications/app_test/test_rbtree/img/result.png b/APP_Framework/Applications/app_test/test_rbtree/img/result.png new file mode 100644 index 000000000..b4e7d176f Binary files /dev/null and b/APP_Framework/Applications/app_test/test_rbtree/img/result.png differ diff --git a/APP_Framework/Applications/app_test/test_rbtree/rbtree.c b/APP_Framework/Applications/app_test/test_rbtree/rbtree.c index 8d4b7e665..d65d4a6b3 100644 --- a/APP_Framework/Applications/app_test/test_rbtree/rbtree.c +++ b/APP_Framework/Applications/app_test/test_rbtree/rbtree.c @@ -1,3 +1,22 @@ +/* +* 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 rbtree.c + * @author 好果汁有限公司 + * @brief 红黑树功能实现文件,包括插入,删除,左旋,右旋,查找,先序遍历,层序遍历等功能 + * @version 0.1 + * @date 2023-07-26 + */ #include "rbtree.h" #include #include @@ -5,14 +24,14 @@ struct Queue* front = NULL; struct Queue* rear = NULL; -struct Node* pfront() +struct Node* PFront() { struct Node* data ; data = front->data; return data; } -int isempty() +int IsEmpty() { if(front==NULL) return 1; @@ -21,9 +40,9 @@ int isempty() return 0; } -void dequeue() +void DeQueue() { - if(isempty()) + if(IsEmpty()) return ; struct Queue* temp = front; @@ -32,7 +51,7 @@ void dequeue() } -void enqueue(struct Node* data) +void EnQueue(struct Node* data) { struct Queue* temp =(struct Queue*)malloc(sizeof(struct Queue)); temp->data = data; @@ -48,28 +67,39 @@ void enqueue(struct Node* data) rear = temp; } -void levelorder(struct Node* root) +/** + * @brief 层级遍历 + * + * @param root + */ +void LevelOrder(struct Node* root) { if(root==NULL) return; - enqueue(root); + EnQueue(root); - while(!isempty()) + while(!IsEmpty()) { - struct Node* current = pfront(); + struct Node* current = PFront(); printf("%d ",current->data); if(current->left!=NULL) - enqueue(current->left); + EnQueue(current->left); if(current->right!=NULL) - enqueue(current->right); + EnQueue(current->right); - dequeue(); + DeQueue(); } } +/** + * @brief 对x节点左旋 + * + * @param T + * @param x + */ void LeftRotate(struct Node** T,struct Node** x) { struct Node* y = (*x)->right; @@ -94,6 +124,13 @@ void LeftRotate(struct Node** T,struct Node** x) (*x)->parent = y; } + +/** + * @brief 对x节点右旋 + * + * @param T + * @param x + */ void RightRotate(struct Node** T,struct Node** x) { struct Node* y = (*x)->left; @@ -118,7 +155,13 @@ void RightRotate(struct Node** T,struct Node** x) } -void RB_insert_fixup(struct Node** T, struct Node** z) +/** + * @brief 插入节点z后调整红黑树 + * + * @param T + * @param z + */ +void RbInsertFixup(struct Node** T, struct Node** z) { struct Node* grandparent = NULL; struct Node* parentpt = NULL; @@ -188,7 +231,14 @@ void RB_insert_fixup(struct Node** T, struct Node** z) } -struct Node* RB_insert(struct Node* T,int data) +/** + * @brief 插入数据data + * + * @param T + * @param data + * @return struct Node* + */ +struct Node* RbInsert(struct Node* T,int data) { struct Node* z = (struct Node*)malloc(sizeof(struct Node)); z->data = data; @@ -220,22 +270,33 @@ struct Node* RB_insert(struct Node* T,int data) else y->right = z; - RB_insert_fixup(&T,&z); + RbInsertFixup(&T,&z); return T; } -void preorder(struct Node* root) +/** + * @brief 先序遍历 + * + * @param root + */ +void PreOrder(struct Node* root) { if(root==NULL) return; printf("%d ",root->data); - preorder(root->left); - preorder(root->right); + PreOrder(root->left); + PreOrder(root->right); } -struct Node* Tree_minimum(struct Node* node) +/** + * @brief 查找node的开始的最小值 + * + * @param node + * @return struct Node* + */ +struct Node* TreeMinimum(struct Node* node) { while(node->left!=NULL) node = node->left; @@ -243,7 +304,13 @@ struct Node* Tree_minimum(struct Node* node) return node; } -void RB_delete_fixup(struct Node** T, struct Node** x) +/** + * @brief 删除节点x后修正红黑树 + * + * @param T + * @param x + */ +void RbDeleteFixup(struct Node** T, struct Node** x) { while((*x)!=*T && (*x)->color == BLACK) { @@ -323,7 +390,14 @@ void RB_delete_fixup(struct Node** T, struct Node** x) } -void RB_transplat(struct Node** T, struct Node** u,struct Node** v) +/** + * @brief 删除节点u,并用v代替u的位置 + * + * @param T + * @param u + * @param v + */ +void RbTransplat(struct Node** T, struct Node** u,struct Node** v) { if((*u)->parent == NULL) *T = *v; @@ -337,10 +411,17 @@ void RB_transplat(struct Node** T, struct Node** u,struct Node** v) (*v)->parent = (*u)->parent; } -struct Node* RB_delete(struct Node *T,struct Node* z) +/** + * @brief 删除节点z + * + * @param T + * @param z + * @return struct Node* + */ +struct Node* RbDelete(struct Node *T,struct Node* z) { struct Node *y = z; - enum type yoc; + enum Type yoc; yoc = z->color; // y's original color struct Node* x; @@ -348,18 +429,18 @@ struct Node* RB_delete(struct Node *T,struct Node* z) if(z->left==NULL ) { x = z->right; - RB_transplat(&T,&z,&(z->right)); + RbTransplat(&T,&z,&(z->right)); } else if(z->right==NULL ) { x = z->left; - RB_transplat(&T,&z,&(z->left)); + RbTransplat(&T,&z,&(z->left)); } else { - y = Tree_minimum(z->right); + y = TreeMinimum(z->right); yoc = y->color; x = y->right; @@ -368,30 +449,37 @@ struct Node* RB_delete(struct Node *T,struct Node* z) else { - RB_transplat(&T,&y,&(y->right)); + RbTransplat(&T,&y,&(y->right)); y->right = z->right; y->right->parent = y; } - RB_transplat(&T,&z,&y); + RbTransplat(&T,&z,&y); y->left = z->left; y->left->parent = y; y->color = z->color; } if(yoc==BLACK) - RB_delete_fixup(&T,&x); + RbDeleteFixup(&T,&x); return T; } -struct Node* BST_search(struct Node* root, int x) +/** + * @brief 查找x对应的节点 + * + * @param root + * @param x + * @return struct Node* + */ +struct Node* BstSearch(struct Node* root, int x) { if(root==NULL || root->data == x) return root; if(root->data > x) - return BST_search(root->left,x); + return BstSearch(root->left,x); else - return BST_search(root->right,x); + return BstSearch(root->right,x); } \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_rbtree/rbtree.h b/APP_Framework/Applications/app_test/test_rbtree/rbtree.h index 68137bb82..f64e3d934 100644 --- a/APP_Framework/Applications/app_test/test_rbtree/rbtree.h +++ b/APP_Framework/Applications/app_test/test_rbtree/rbtree.h @@ -1,5 +1,26 @@ -#ifndef __LIST_H__ -#define __LIST_H__ +/* +* 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 rbtree.h + * @author 好果汁有限公司 + * @brief 红黑树数据结构和功能函数定义与声明 + * @version 0.1 + * @date 2023-07-26 + */ + + +#ifndef __RBTREE_H__ +#define __RBTREE_H__ #include #include @@ -10,7 +31,7 @@ extern "C" { #endif -enum type {RED,BLACK}; +enum Type {RED,BLACK}; struct Node { @@ -18,7 +39,7 @@ struct Node struct Node* left; struct Node* right; struct Node* parent; - enum type color; + enum Type color; }; struct Queue @@ -29,34 +50,35 @@ struct Queue -struct Node *pfront(); -int isempty(); +struct Node *PFront(); -void dequeue(); +int IsEmpty(); -void enqueue(struct Node *data); +void DeQueue(); -void levelorder(struct Node *root); +void EnQueue(struct Node *data); + +void LevelOrder(struct Node *root); void LeftRotate(struct Node **T, struct Node **x); void RightRotate(struct Node **T, struct Node **x); -void RB_insert_fixup(struct Node **T, struct Node **z); +void RbInsertFixup(struct Node **T, struct Node **z); -struct Node *RB_insert(struct Node *T, int data); +struct Node *RbInsert(struct Node *T, int data); -void preorder(struct Node *root); +void PreOrder(struct Node *root); -struct Node *Tree_minimum(struct Node *node); +struct Node *TreeMinimum(struct Node *node); -void RB_delete_fixup(struct Node **T, struct Node **x); +void RbDeleteFixup(struct Node **T, struct Node **x); -void RB_transplat(struct Node **T, struct Node **u, struct Node **v); +void RbTransplat(struct Node **T, struct Node **u, struct Node **v); -struct Node *RB_delete(struct Node *T, struct Node *z); +struct Node *RbDelete(struct Node *T, struct Node *z); -struct Node *BST_search(struct Node *root, int x); +struct Node *BstSearch(struct Node *root, int x); #ifdef __cplusplus } diff --git a/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.c b/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.c index 13ddd6950..ae7006886 100644 --- a/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.c +++ b/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.c @@ -1,3 +1,22 @@ +/* +* 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_rbtree.c + * @author 好果汁有限公司 + * @brief 红黑树测试文件 + * @version 0.1 + * @date 2023-07-26 + */ #include #include #include @@ -8,40 +27,40 @@ extern struct Queue* front; extern struct Queue* rear; -void Test_Rbtree(void) +void TestRbtree(void) { struct Node* RBT = NULL; - RBT = RB_insert(RBT,2); - RBT = RB_insert(RBT,1); - RBT = RB_insert(RBT,4); - RBT = RB_insert(RBT,5); - RBT = RB_insert(RBT,9); - RBT = RB_insert(RBT,3); - RBT = RB_insert(RBT,6); - RBT = RB_insert(RBT,7); + RBT = RbInsert(RBT,2); + RBT = RbInsert(RBT,1); + RBT = RbInsert(RBT,4); + RBT = RbInsert(RBT,5); + RBT = RbInsert(RBT,9); + RBT = RbInsert(RBT,3); + RBT = RbInsert(RBT,6); + RBT = RbInsert(RBT,7); - printf("\nPreorder - "); - preorder(RBT); + printf("\nPreOrder - "); + PreOrder(RBT); printf("\nLevel order - "); - levelorder(RBT); + LevelOrder(RBT); - struct Node* x = BST_search(RBT,5); - - RBT = RB_delete(RBT,x); + struct Node* x = BstSearch(RBT,5); + RBT = RbDelete(RBT,x); + printf("\nAfter deleting 5"); - printf("\nPreorder - "); - preorder(RBT); + printf("\nPreOrder - "); + PreOrder(RBT); front = NULL; rear = NULL; // Delete old Queue printf("\nLevel order - "); - levelorder(RBT); + LevelOrder(RBT); - return ; + // return ; } -PRIV_SHELL_CMD_FUNCTION(Test_Rbtree, a red black sample , PRIV_SHELL_CMD_MAIN_ATTR); +PRIV_SHELL_CMD_FUNCTION(TestRbtree, a red black sample , PRIV_SHELL_CMD_MAIN_ATTR);