diff --git a/APP_Framework/Applications/app_test/Kconfig b/APP_Framework/Applications/app_test/Kconfig index 45df5f5d5..f7684440a 100644 --- a/APP_Framework/Applications/app_test/Kconfig +++ b/APP_Framework/Applications/app_test/Kconfig @@ -240,5 +240,9 @@ menu "test app" bool "Config test soft timer" default n + menuconfig USER_TEST_RBTREE + bool "Config test rbtree" + default n + endif endmenu diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index 1cf919846..000d2caa3 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -101,5 +101,9 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y) SRC_FILES += test_timer.c endif + ifeq ($(CONFIG_USER_TEST_RBTREE),y) + SRC_FILES += test_rbtree/test_rbtree.c + endif + include $(KERNEL_ROOT)/compiler.mk endif diff --git a/APP_Framework/Applications/app_test/test_rbtree/README.md b/APP_Framework/Applications/app_test/test_rbtree/README.md new file mode 100644 index 000000000..2ad59157d --- /dev/null +++ b/APP_Framework/Applications/app_test/test_rbtree/README.md @@ -0,0 +1,52 @@ +# 基于k210-emulator实现基数树并测试验证 + +## 1. 简介 + +基于矽璓模拟器cortex-m4-emulator,实现红黑树,并编写测试程序在shell终端打印结果 + +## 2. 数据结构设计说明 + +红黑树设计为: + +```c +typedef struct rb_node { + int data; // 节点数据 + int color; // 节点颜色:0表示黑色,1表示红色 + struct rb_node* parent; // 父节点指针 + struct rb_node* left; // 左子节点指针 + struct rb_node* right; // 右子节点指针 +} Node; + +// 红黑树结构 +typedef struct rb_tree { + Node* root; // 根节点指针 + Node* nil; // NIL节点指针(表示叶子节点,颜色为黑色) +} Tree; +``` + +其中,节点在树中的路径即为键,`data` 存储值,`color` 定义为 节点颜色,0表示黑色,1表示红色 + +一共实现了 7 个函数,分别为: + +- `CreateNode`:创建一个节点 +- `CreateTree`:创建红黑树 +- `leftRotate`:左旋 +- `rightRotate`:右旋 +- `insertFixup`:插入修正函数 +- `insert`:插入键值对 +- `inorderTraversal`:中序遍历 + +## 3. 测试程序说明 + +测试程序 `TestRbtree` 已经注册为 shell 命令,可以调用执行。 + +## 4. 运行结果(##需结合运行测试截图按步骤说明##) + +1. 在工作区终端中输入命令:`make BOARD=cortex-m4-emulator menuconfig`,进入配置页面,依次进入 `APP_Framework` -> `Applications` -> `test app` 目录,将 `Enable application test function` 选项置为 `Y`,进入 `Enable application test function` 将 `Config test rbtree` 选项置为 `Y`,一直选择 `Exit` 退出配置,在最后需要确认的页面选择 `Yes` 保存配置。 +![fig1](fig1.png) +2. 执行编译命令:`make BOARD=cortex-m4-emulator`,正常情况下应当编译无误 +![fig2](fig2.png) +3. 在 `qemu` 中运行:`qemu-system-arm -machine netduinoplus2 -nographic -kernel build/XiZi-cortex-m4-emulator.elf` +![fig3](fig3.png) +4. 在 shell 中运行命令 `TestRbtree`,执行结果与预期一致,验证完成。 +![fig4](fig4.png) \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_rbtree/fig1.png b/APP_Framework/Applications/app_test/test_rbtree/fig1.png new file mode 100644 index 000000000..28fe87f6c Binary files /dev/null and b/APP_Framework/Applications/app_test/test_rbtree/fig1.png differ diff --git a/APP_Framework/Applications/app_test/test_rbtree/fig2.png b/APP_Framework/Applications/app_test/test_rbtree/fig2.png new file mode 100644 index 000000000..f62e10544 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_rbtree/fig2.png differ diff --git a/APP_Framework/Applications/app_test/test_rbtree/fig3.png b/APP_Framework/Applications/app_test/test_rbtree/fig3.png new file mode 100644 index 000000000..35cde4d18 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_rbtree/fig3.png differ diff --git a/APP_Framework/Applications/app_test/test_rbtree/fig4.png b/APP_Framework/Applications/app_test/test_rbtree/fig4.png new file mode 100644 index 000000000..3ed2b9276 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_rbtree/fig4.png differ diff --git a/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.c b/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.c new file mode 100644 index 000000000..253a55935 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.c @@ -0,0 +1,165 @@ +/** +* @file: test_rbtree.c +* @brief: Implement a simple red black tree +* @version: 1.0 +* @date: 2023/7/12 +* @param _desc Implement a simple red black tree +*/ + +#include "test_rbtree.h" + +// 创建新节点 +Node* createNode(int data) { + Node* node = (Node*)malloc(sizeof(Node)); + node->data = data; + node->color = 1; // 默认为红色 + node->parent = NULL; + node->left = NULL; + node->right = NULL; + return node; +} + +// 初始化红黑树 +Tree* createTree() { + Tree* tree = (Tree*)malloc(sizeof(Tree)); + tree->nil = createNode(0); + tree->nil->color = 0; // NIL节点颜色为黑色 + tree->root = tree->nil; + return tree; +} + +// 左旋操作 +void leftRotate(Tree* tree, Node* x) { + Node* y = x->right; + x->right = y->left; + if (y->left != tree->nil) { + y->left->parent = x; + } + y->parent = x->parent; + if (x->parent == tree->nil) { + tree->root = y; + } else if (x == x->parent->left) { + x->parent->left = y; + } else { + x->parent->right = y; + } + y->left = x; + x->parent = y; +} + +// 右旋操作 +void rightRotate(Tree* tree, Node* y) { + Node* x = y->left; + y->left = x->right; + if (x->right != tree->nil) { + x->right->parent = y; + } + x->parent = y->parent; + if (y->parent == tree->nil) { + tree->root = x; + } else if (y == y->parent->left) { + y->parent->left = x; + } else { + y->parent->right = x; + } + x->right = y; + y->parent = x; +} + +// 插入修正函数 +void insertFixup(Tree* tree, Node* z) { + while (z->parent->color == 1) { + if (z->parent == z->parent->parent->left) { + Node* y = z->parent->parent->right; + if (y->color == 1) { + z->parent->color = 0; + y->color = 0; + z->parent->parent->color = 1; + z = z->parent->parent; + } else { + if (z == z->parent->right) { + z = z->parent; + leftRotate(tree, z); + } + z->parent->color = 0; + z->parent->parent->color = 1; + rightRotate(tree, z->parent->parent); + } + } else { + Node* y = z->parent->parent->left; + if (y->color == 1) { + z->parent->color = 0; + y->color = 0; + z->parent->parent->color = 1; + z = z->parent->parent; + } else { + if (z == z->parent->left) { + z = z->parent; + rightRotate(tree, z); + } + z->parent->color = 0; + z->parent->parent->color = 1; + leftRotate(tree, z->parent->parent); + } + } + } + tree->root->color = 0; +} + +// 插入节点 +void insert(Tree* tree, int data) { + Node* z = createNode(data); + Node* y = tree->nil; + Node* x = tree->root; + while (x != tree->nil) { + y = x; + if (z->data < x->data) { + x = x->left; + } else { + x = x->right; + } + } + z->parent = y; + if (y == tree->nil) { + tree->root = z; + } else if (z->data < y->data) { + y->left = z; + } else { + y->right = z; + } + z->left = tree->nil; + z->right = tree->nil; + z->color = 1; + insertFixup(tree, z); +} + +// 中序遍历红黑树 +void inorderTraversal(Tree* tree, Node* node) { + if (node != tree->nil) { + inorderTraversal(tree, node->left); + printf("%d ", node->data); + inorderTraversal(tree, node->right); + } +} + +// 测试红黑树实现 +void TestRbtree() { + Tree* tree = createTree(); + int random_numbers[10]; + srand(time(NULL)); + printf("插入数组:"); + for (int i=0; i<10; i++) { + random_numbers[i] = rand() % 101; + printf("%d ", random_numbers[i]); + } + printf("\n"); + for (int i=0; i<10; i++) { + insert(tree, random_numbers[i]); + } + + printf("红黑树中序遍历结果:"); + inorderTraversal(tree, tree->root); + printf("\n"); +} + +PRIV_SHELL_CMD_FUNCTION(TestRbtree, _desc, PRIV_SHELL_CMD_MAIN_ATTR); \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.h b/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.h new file mode 100644 index 000000000..0874b3773 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.h @@ -0,0 +1,33 @@ +#ifndef _TEST_RBTREE_H_ +#define _TEST_RBTREE_H_ + +#include +#include +#include +#include + +typedef struct rb_node { + int data; // 节点数据 + int color; // 节点颜色:0表示黑色,1表示红色 + struct rb_node* parent; // 父节点指针 + struct rb_node* left; // 左子节点指针 + struct rb_node* right; // 右子节点指针 +} Node; + +// 红黑树结构 +typedef struct rb_tree { + Node* root; // 根节点指针 + Node* nil; // NIL节点指针(表示叶子节点,颜色为黑色) +} Tree; + +// 创建新节点 +Node* createNode(int data); +Tree* createTree(); +void leftRotate(Tree* tree, Node* x); +void rightRotate(Tree* tree, Node* y); +void insertFixup(Tree* tree, Node* z); +void insert(Tree* tree, int data); +void inorderTraversal(Tree* tree, Node* node); +// void TestRbtree(); + +#endif \ No newline at end of file