diff --git a/APP_Framework/Applications/app_test/test_rbtree/README.md b/APP_Framework/Applications/app_test/test_rbtree/README.md old mode 100644 new mode 100755 index 4841e4ed0..cca225b39 --- a/APP_Framework/Applications/app_test/test_rbtree/README.md +++ b/APP_Framework/Applications/app_test/test_rbtree/README.md @@ -1,69 +1,79 @@ # 基于cortex-m4-emulator实现红黑树并测试验证 ## 1. 简介 -红黑树是一种自平衡的二叉查找树,具有良好的插入、删除和查找性能,本次提交结果为红黑树数据结构的简单实现。test_rbtree.h中定义了红黑树的数据结构和声明插入、删除、查找相关操作函数;test_rbtree.c中为操作函数的定义,并提供了测试函数TestRBTree用于验证红黑树的正确性。 +红黑树是一棵二叉查找树,它在每个结点上增加了一个存储位表示结点的颜色,可以是红色(RED)或黑色(BLACK)。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其它路径长出俩倍,因而是近似平衡的。红黑树具有良好的插入、删除和查找性能,本次提交结果为红黑树数据结构的简单实现。test_rbtree.h中定义了红黑树的数据结构和声明插入、删除、查找相关操作函数;test_rbtree.c中为操作函数的定义,并提供了测试函数RBTreeTest用于验证红黑树的正确性。 ## 2. 数据结构设计说明 -**RBNodeType 结构体** -用来存储一个红黑树结点的相关信息 -- key:节点的键值 -- left_child:指向左子节点的指针 -- right_child:指向右子节点的指针 -- parent:指向父节点的指针 -- is_red:表示节点的颜色,true表示红色,false表示黑色 - **RBTreeType 结构体** -用来存储一个红黑树的相关信息 -- root:指向红黑树的根节点的指针 -- leaf:红黑树的叶节点,由于叶节点并不需要存储数据,故每棵树只分配一个叶节点 +用来存储一个红黑树结点的相关信息 +- key:结点的键值 +- left_child:指向左子结点的指针 +- right_child:指向右子结点的指针 +- parent:指向父结点的指针 +- color:表示结点颜色,类型为 ColorType(RED表示红色,BLACK表示黑色) +**RBTreeRootType 结构体** +用来存储红黑树根结点的相关信息 +- root:指向红黑树的根结点的指针 +- nil:指向红黑树的叶结点,由于叶结点并不需要存储数据,故每棵树只分配一个叶结点 -**RBTreeTraversal 函数** -该函数用于遍历红黑树并打印节点的键值。采用中序遍历的方式,递归地遍历左子树、当前节点和右子树。 +**RBTreeInit函数** +该函数实现红黑树的初始化。创建一个根结点和一个哨兵结点,然后将根结点指向哨兵结点。返回创建的红黑树的根结点。 + +**RBTreeHandleReorient函数** +该函数实现红黑树的重新定向。主要用于插入和删除操作后的调整。它会根据红黑树的性质进行左旋、右旋和颜色调整。 + +**RBTreeTransplant函数** +该函数实现红黑树的子树替换。用于替换红黑树中的结点。它将结点 node 替换为结点 child。 **RBTreeLeftRotate 函数** -该函数实现红黑树的左旋转操作。接受一个当前节点指针作为参数,并按照左旋转的规则调整节点和子树的位置。 +该函数实现红黑树的左旋转操作。接受一个当前结点指针作为参数,并按照左旋转的规则调整结点和子树的位置。 **RBTreeRightRotate 函数** -该函数实现红黑树的右旋转操作。接受一个当前节点指针作为参数,并按照右旋转的规则调整节点和子树的位置。 +该函数实现红黑树的右旋转操作。接受一个当前结点指针作为参数,并按照右旋转的规则调整结点和子树的位置。 -**InsertFixup 函数** -该函数用于插入节点后修复红黑树的平衡性。接受一个当前节点指针作为参数,并根据红黑树的性质进行旋转和着色操作,以恢复平衡。 +**RBTreeFindMin函数** +该函数用于查找红黑树中最小值。 + +**RBTreeFindMax函数** +该函数用于查找红黑树中最大值。 **RBTreeInsert 函数** -该函数用于向红黑树中插入一个新节点。接受一个新节点指针作为参数,并根据新节点的键值插入到适当的位置,然后调用 InsertFixup 进行修复。 - -**DeleteFixup 函数** -该函数用于删除节点后修复红黑树的平衡性。接受一个当前节点指针作为参数,并根据红黑树的性质进行旋转和着色操作,以恢复平衡。 +该函数用于向红黑树中插入一个新结点。如果插入成功,返回新的红黑树的根结点。 **RBTreeDelete 函数** -该函数用于从红黑树中删除指定节点。接受一个目标节点指针作为参数,并根据不同的情况进行节点的替换和删除操作,然后调用 DeleteFixup 进行修复。 +该函数用于从红黑树中删除指定结点。如果删除成功,返回新的红黑树的根结点。 -**FindSuccessor 函数** -该函数用于查找给定节点的后继节点。接受一个当前节点指针作为参数,并在红黑树中找到当前节点的后继节点。 +**RBTreePrePrint函数** +该函数用于遍历红黑树并打印结点的键值。采用先序遍历的方式,打印每个结点的键值和颜色。 -**RBTreeSearch 函数** -该函数用于在红黑树中查找指定键值的节点。接受一个键值作为参数,并在红黑树中进行查找,返回找到的节点指针。 +**RBTreeInPrin函数** +该函数用于遍历红黑树并打印结点的键值。采用中序遍历的方式,打印每个结点的键值和颜色。 + +**RBTreePrint函数** +该函数用于遍历红黑树。打印红黑树的前序和中序遍历结果。 + +**RBTreeTest函数** +该函数用于测试红黑树的功能和正确性。测试红黑树的功能,包括初始化、插入、删除和打印操作。 ## 3. 测试程序说明 -TestRBTree用于验证红黑树的功能和正确性,下面是该程序的使用步骤和说明: -- 函数中定义一个默认关键字数组,其中包含了20个整数关键字,运行时自动遍历数组构建红黑树,构建完成后中序遍历输出结果,可以根据输出结果验证红黑树的节点顺序以及颜色是否符合预期。 -- 对关键字数组中的每个关键字,在红黑树中进行搜索,并输出找到节点的父节点、左子节点和右子节点的关键字,随后删除该节点。 -- 在每次删除操作后,程序会询问是否显示当前的红黑树。如果输入 "Y" 或 "y",将再次进行中序遍历,并输出当前红黑树中的结点,可以根据输出结果查看结点是否符合预期。当树空时结束程序。 - +RBTreeTest用于验证红黑树的功能和正确性,下面是该程序的使用步骤和说明: +- 函数中定义一个默认关键字数组,其中包含了9个整数关键字,运行时自动遍历数组构建红黑树,构建完成后输出前序遍历和中序遍历结果,可以根据输出结果验证红黑树的结点顺序以及颜色是否符合预期。 +- 删除5个结点,删除后再次输出当前红黑树中结点前序遍历和中序遍历结果。 ## 4. 运行结果(##需结合运行测试截图按步骤说明##) 根据默认关键字数组构建红黑树 -![Alt text](image.png) +![Alt text](image1.png) -根据键值查找结点,输出相关信息并删除,可以输入'Y'或'y'展示删除后的红黑树 +此时红黑树中结点前序遍历和中序遍历 -![Alt text](image-1.png) +![Alt text](image2.png) -到达空树,退出程序 +删除5个结点,当前红黑树中结点前序遍历和中序遍历 + +![Alt text](image3.png) -![Alt text](image-2.png) diff --git a/APP_Framework/Applications/app_test/test_rbtree/image-1.png b/APP_Framework/Applications/app_test/test_rbtree/image-1.png deleted file mode 100644 index 48ed6fb1a..000000000 Binary files a/APP_Framework/Applications/app_test/test_rbtree/image-1.png and /dev/null differ diff --git a/APP_Framework/Applications/app_test/test_rbtree/image-2.png b/APP_Framework/Applications/app_test/test_rbtree/image-2.png deleted file mode 100644 index 578024325..000000000 Binary files a/APP_Framework/Applications/app_test/test_rbtree/image-2.png and /dev/null differ diff --git a/APP_Framework/Applications/app_test/test_rbtree/image.png b/APP_Framework/Applications/app_test/test_rbtree/image.png deleted file mode 100644 index 40d78288f..000000000 Binary files a/APP_Framework/Applications/app_test/test_rbtree/image.png and /dev/null differ diff --git a/APP_Framework/Applications/app_test/test_rbtree/image1.png b/APP_Framework/Applications/app_test/test_rbtree/image1.png new file mode 100755 index 000000000..e78e2f78d Binary files /dev/null and b/APP_Framework/Applications/app_test/test_rbtree/image1.png differ diff --git a/APP_Framework/Applications/app_test/test_rbtree/image2.png b/APP_Framework/Applications/app_test/test_rbtree/image2.png new file mode 100755 index 000000000..87484cd49 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_rbtree/image2.png differ diff --git a/APP_Framework/Applications/app_test/test_rbtree/image3.png b/APP_Framework/Applications/app_test/test_rbtree/image3.png new file mode 100755 index 000000000..eb17f728a Binary files /dev/null and b/APP_Framework/Applications/app_test/test_rbtree/image3.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 old mode 100644 new mode 100755 index 6f25376df..5cdfe9365 --- a/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.c +++ b/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.c @@ -1,341 +1,372 @@ -/* -* Copyright (c) 2023 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 -* @brief: a application of red-black tree function -* @version: 1.0 -* @author: AIIT XUOS Lab -* @date: 2023/6/23 -*/ -#include -#include -#include"test_rbtree.h" -#ifdef ADD_XIZI_FEATURES - -void RBTreeTraversal(RBTreeType *tree, RBNodeType *node) -{ - if (node != tree->leaf) { - RBTreeTraversal(tree, node->left_child); - printf("key:%d, color:%s\n", node->key, (node->is_red ? "Red" : "Black")); - RBTreeTraversal(tree, node->right_child); - } -} - -RBNodeType* RBTreeSearch(RBTreeType *tree, int key) -{ - RBNodeType* current_node = tree->root; - while (current_node != tree->leaf){ - if (key < current_node->key) - current_node = current_node->left_child; - else if (key > current_node->key) - current_node = current_node->right_child; - else - return current_node; - } - - return tree->leaf; -} - -void RBTreeLeftRotate(RBTreeType *tree, RBNodeType *current_node) -{ - RBNodeType* child_node = current_node->right_child; - - current_node->right_child = child_node->left_child; - if (child_node->left_child != tree->leaf) - child_node->left_child->parent = current_node; - - child_node->parent = current_node->parent; - if (current_node->parent == tree->leaf) - tree->root = child_node; - else if (current_node == current_node->parent->left_child) - current_node->parent->left_child = child_node; - else - current_node->parent->right_child = child_node; - - child_node->left_child = current_node; - current_node->parent = child_node; -} - -void RBTreeRightRotate(RBTreeType *tree, RBNodeType* current_node) -{ - RBNodeType* child_node = current_node->left_child; - - current_node->left_child = child_node->right_child; - if (child_node->right_child != tree->leaf) - child_node->right_child->parent = current_node; - - child_node->parent = current_node->parent; - if (current_node->parent == tree->leaf) - tree->root = child_node; - else if (current_node == current_node->parent->right_child) - current_node->parent->right_child = child_node; - else - current_node->parent->left_child = child_node; - - child_node->right_child = current_node; - current_node->parent = child_node; -} - -void InsertFixup(RBTreeType *tree, RBNodeType* current_node) -{ - while (current_node->parent->is_red){ - /* The parent of current_node is the left subtree of the grandfather */ - if (current_node->parent == current_node->parent->parent->left_child){ - RBNodeType * uncle_node = current_node->parent->parent->right_child; - if (uncle_node->is_red){ /* case1:red uncle and red parent, change color */ - uncle_node->is_red = false; - current_node->parent->is_red = false; - current_node->parent->parent->is_red = true; - - current_node = current_node->parent->parent; - }else{ /* case2:black uncle and red parent, need rotation */ - if (current_node->parent->right_child == current_node){ - current_node = current_node->parent; - RBTreeLeftRotate(tree, current_node); - } - - current_node->parent->is_red = false; - current_node->parent->parent->is_red = true; - RBTreeRightRotate(tree, current_node->parent->parent); - } - /* The parent of current_node is the right subtree of the grandfather, same with left subtree */ - }else{ - RBNodeType * uncle_node = current_node->parent->parent->left_child; - if (uncle_node->is_red){ - uncle_node->is_red = false; - current_node->parent->is_red = false; - current_node->parent->parent->is_red = true; - - current_node = current_node->parent->parent; - }else{ - if (current_node->parent->left_child == current_node){ - current_node = current_node->parent; - RBTreeRightRotate(tree, current_node); - } - - current_node->parent->is_red = false; - current_node->parent->parent->is_red = true; - RBTreeLeftRotate(tree, current_node->parent->parent); - } - } - } - tree->root->is_red = false; -} - -void RBTreeInsert(RBTreeType *tree, RBNodeType* new_node) -{ - RBNodeType* previous_node = tree->root; - RBNodeType* current_node = tree->root; - - while (current_node != tree->leaf){ - previous_node = current_node; - if (new_node->key > current_node->key) - current_node = current_node->right_child; - else if (new_node->key < current_node->key) - current_node = current_node->left_child; - else - return; - } - - if (previous_node == tree->leaf){ - tree->root = new_node; - tree->root->parent = tree->leaf; - }else{ - new_node->parent = previous_node; - - if (previous_node->key > new_node->key) - previous_node->left_child = new_node; - else - previous_node->right_child = new_node; - } - - InsertFixup(tree, new_node); -} - -RBNodeType* FindSuccessor(RBTreeType *tree, RBNodeType* current_node) -{ - RBNodeType* parent_node = current_node->parent; - if (current_node->right_child != tree->leaf){ - current_node = current_node->right_child; - while (current_node->left_child != tree->leaf) - current_node = current_node->left_child; - return current_node; - } - - while ((parent_node != tree->leaf) && (current_node == parent_node->right_child)){ - current_node = parent_node; - parent_node = parent_node->parent; - } - return parent_node; -} - -void DeleteFixup(RBTreeType *tree, RBNodeType* current_node) -{ - while ((current_node != tree->root) && (current_node->is_red == false)){ - if (current_node == current_node->parent->left_child){ - - RBNodeType* brother_node = current_node->parent->right_child; - if (brother_node->is_red){ - brother_node->is_red = false; - current_node->parent->is_red = true; - RBTreeLeftRotate(tree, current_node->parent); - brother_node = current_node->parent->right_child; - } - - if ((brother_node->left_child->is_red == false) && (brother_node->right_child->is_red == false)){ - brother_node->is_red = true; - current_node = current_node->parent; - }else{ - if (brother_node->right_child->is_red == false){ - brother_node->left_child->is_red = false; - brother_node->is_red = true; - RBTreeRightRotate(tree, brother_node); - brother_node = current_node->parent->right_child; - } - - brother_node->is_red = current_node->parent->is_red; - current_node->parent->is_red = false; - brother_node->right_child->is_red = false; - RBTreeLeftRotate(tree, current_node->parent); - current_node = tree->root; - } - }else{ - RBNodeType* brother_node = current_node->parent->left_child; - if (brother_node->is_red){ - brother_node->is_red = false; - current_node->parent->is_red = true; - RBTreeRightRotate(tree, current_node->parent); - brother_node = current_node->parent->left_child; - } - - if ((brother_node->left_child->is_red == false) && (brother_node->right_child->is_red == false)){ - brother_node->is_red = true; - current_node = current_node->parent; - }else{ - if (brother_node->left_child->is_red == false){ - brother_node->right_child->is_red = false; - brother_node->is_red = true; - RBTreeLeftRotate(tree, brother_node); - brother_node = current_node->parent->left_child; - } - - brother_node->is_red = current_node->parent->is_red; - current_node->parent->is_red = false; - brother_node->left_child->is_red = false; - RBTreeRightRotate(tree, current_node->parent); - current_node = tree->root; - } - } - } - current_node->is_red = false; -} - -void RBTreeDelete(RBTreeType *tree, RBNodeType* target_node) -{ - RBNodeType* delete_node = tree->leaf; - RBNodeType* replace_node = tree->leaf; - - if ((target_node->left_child == tree->leaf) || (target_node->right_child == tree->leaf)) - delete_node = target_node; - else - delete_node = FindSuccessor(tree, target_node); - - if (delete_node->left_child != tree->leaf) /* successor still has subtree */ - replace_node = delete_node->left_child; - else if (delete_node->right_child != tree->leaf) - replace_node = delete_node->right_child; - - replace_node->parent = delete_node->parent; - - if (delete_node->parent == tree->leaf) /* delete a root node */ - tree->root = replace_node; - else if (delete_node == delete_node->parent->left_child) - delete_node->parent->left_child = replace_node; - else - delete_node->parent->right_child = replace_node; - - if (delete_node != target_node) - target_node->key = delete_node->key; - - if (delete_node->is_red == false) - DeleteFixup(tree, replace_node); - - free(delete_node); -} - - -void TestRBTree(void) -{ - int default_key[] = { 16, 25, 23, 5, 2, 6, 17, 37, 38, 98, 20, 19, 47, 49, 12, 21, 9, 18, 14, 15 }; - int array_size = sizeof(default_key) / sizeof(default_key[0]); - - printf("Test Red Black Tree\n"); - printf("default_key array: "); - for (int i = 0; i < array_size; i++) - printf("%d ", default_key[i]); - printf("\n%d elements\n", array_size); - - RBTreeType *tree = (RBTreeType *)malloc(sizeof(RBTreeType)); - if (tree == NULL) { - printf("malloc failed\n"); - return; - } - - tree->leaf = (RBNodeType*)malloc(sizeof(RBNodeType)); - tree->leaf->left_child = NULL; - tree->leaf->right_child = NULL; - tree->leaf->parent = NULL; - tree->leaf->is_red = false; - tree->leaf->key = -1; - tree->root = tree->leaf; - - RBNodeType *node = tree->leaf; - - for (int i = 0; i < array_size; i++) { - node = (RBNodeType*)malloc(sizeof(RBNodeType)); - node->left_child = tree->leaf; - node->right_child = tree->leaf; - node->parent = NULL; - node->is_red = true; - node->key = default_key[i]; - printf("insert key[%d]=%d\n",i,default_key[i]); - RBTreeInsert(tree, node); - } - - printf("------------------Inorder Traversal------------------\n"); - RBTreeTraversal(tree, tree->root); - - for (int i = 0; i < array_size; i++) { - printf("search key = %d\n", default_key[i]); - node = RBTreeSearch(tree, default_key[i]); - printf("search succeeded, parent node: %d, left-child: %d, right-child: %d\n", node->parent->key, node->left_child->key, node->right_child->key); - - printf("delete key = %d\n", node->key); - RBTreeDelete(tree, node); - - printf("Show current tree?Y/N \n"); - char ch; - scanf("%c", &ch); - if (ch == 'Y' || ch == 'y') { - printf("------------------Inorder Traversal Tree After Deletion------------------\n"); - if (tree->root != tree->leaf) - RBTreeTraversal(tree, tree->root); - else - printf("the tree is empty.\n"); - } - } -} - -PRIV_SHELL_CMD_FUNCTION(TestRBTree, a red-black tree test sample, PRIV_SHELL_CMD_MAIN_ATTR); - -#endif \ No newline at end of file +/* +* Copyright (c) 2023 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 +* @brief: a application of red-black tree function +* @version: 1.0 +* @author: 白痴也有春天 +* @date: 2023/9/18 +*/ +#include +#include +#include +#include "test_rbtree.h" +#include +#ifdef ADD_XIZI_FEATURES + +RBTreeRootType *RBTreeInit(void) +{ + RBTreeRootType *TreeRoot; + + TreeRoot = (RBTreeRootType *)malloc(sizeof(RBTreeRootType)); + assert(TreeRoot != NULL); + + TreeRoot->nil = (RBTreeType *)malloc(sizeof(RBTreeType)); + assert(TreeRoot->nil != NULL); + TreeRoot->nil->color = BLACK; + TreeRoot->nil->left = NULL; + TreeRoot->nil->right = NULL; + TreeRoot->nil->parent = NULL; + + TreeRoot->root = TreeRoot->nil; + + return TreeRoot; +} + +static void RBTreeHandleReorient(RBTreeRootType *TreeRoot, RBTreeType *node, int key) +{ + node->color = RED; + node->left->color = BLACK; + node->right->color = BLACK; + + if (node->parent->color == RED){ + node->parent->parent->color = RED; + + if (node->parent->key < node->parent->parent->key){ + if (key > node->parent->key){ + node->color = BLACK; + RBTreeLeftRotate(TreeRoot, node->parent); + RBTreeRightRotate(TreeRoot, node->parent); + }else{ + node->parent->color = BLACK; + RBTreeRightRotate(TreeRoot, node->parent->parent); + } + }else{ + if (key < node->parent->key){ + node->color = BLACK; + RBTreeRightRotate(TreeRoot, node->parent); + RBTreeLeftRotate(TreeRoot, node->parent); + }else{ + node->parent->color = BLACK; + RBTreeLeftRotate(TreeRoot, node->parent->parent); + } + } + } + + TreeRoot->root->color = BLACK; +} + +void RBTreeTransplant(RBTreeRootType *TreeRoot, RBTreeType *node, RBTreeType *child) +{ + if (node->parent == TreeRoot->nil) + TreeRoot->root = child; + else if (node == node->parent->left) + node->parent->left = child; + else + node->parent->right = child; + + child->parent = node->parent; +} + +static void RBTreeLeftRotate(RBTreeRootType *TreeRoot, RBTreeType *node) +{ + RBTreeType *nodeNew = node->right; + node->right = nodeNew->left; + + if (nodeNew->left != TreeRoot->nil) + nodeNew->left->parent = node; + + nodeNew->parent = node->parent; + if (node->parent == TreeRoot->nil) + TreeRoot->root = nodeNew; + else if (node == node->parent->left) + node->parent->left = nodeNew; + else + node->parent->right = nodeNew; + + nodeNew->left = node; + node->parent = nodeNew; +} + +static void RBTreeRightRotate(RBTreeRootType *TreeRoot, RBTreeType *node) +{ + RBTreeType *nodeNew = node->left; + node->left = nodeNew->right; + + if (nodeNew->right != TreeRoot->nil) + nodeNew->right->parent = node; + + nodeNew->parent = node->parent; + if (node->parent == TreeRoot->nil) + TreeRoot->root = nodeNew; + else if (node == node->parent->left) + node->parent->left = nodeNew; + else + node->parent->right = nodeNew; + + nodeNew->right = node; + node->parent = nodeNew; +} + +static RBTreeType *RBTreeFindMin(RBTreeRootType *TreeRoot, RBTreeType *node) +{ + if (node == TreeRoot->nil) + return TreeRoot->nil; + + while (node->left != TreeRoot->nil) + node = node->left; + + return node; +} + +static RBTreeType *RBTreeFindMax(RBTreeRootType *TreeRoot, RBTreeType *node) +{ + if (node == TreeRoot->nil) + return TreeRoot->nil; + + while (node->right != TreeRoot->nil) + node = node->right; + + return node; +} + +RBTreeRootType *RBTreeInsert(RBTreeRootType *TreeRoot, int key) +{ + RBTreeType *node, *parent; + node = TreeRoot->root; + parent = node; + + while (node != TreeRoot->nil){ + if (node != TreeRoot->nil){ + if (node->left->color == RED && node->right->color == RED){ + RBTreeHandleReorient(TreeRoot, node, key); + } + } + + parent = node; + if (key < node->key) + node = node->left; + else if (key > node->key) + node = node->right; + else + return TreeRoot; + } + + node = (RBTreeType *)malloc(sizeof(RBTreeType)); + assert(node != NULL); + node->key = key; + node->color = RED; + node->left = TreeRoot->nil; + node->right = TreeRoot->nil; + node->parent = parent; + + if (TreeRoot->root == TreeRoot->nil) + TreeRoot->root = node; + else if (key < parent->key) + parent->left = node; + else + parent->right = node; + + RBTreeHandleReorient(TreeRoot, node, key); + + return TreeRoot; +} + +RBTreeRootType *RBTreeDelete(RBTreeRootType *TreeRoot, int key) +{ + assert(TreeRoot != NULL); + if (NULL == TreeRoot->root) + return TreeRoot; + + RBTreeType *ToDelete = TreeRoot->root; + RBTreeType *node; + + while (ToDelete != TreeRoot->nil && ToDelete->key != key){ + if (ToDelete->key > key) + ToDelete = ToDelete->left; + else if (ToDelete->key < key) + ToDelete = ToDelete->right; + } + + if (ToDelete == TreeRoot->nil) + return TreeRoot; + + if (ToDelete->left != TreeRoot->nil && ToDelete->right != TreeRoot->nil){ + RBTreeType *alternative = RBTreeFindMin(TreeRoot, ToDelete->right); + key = alternative->key; + ToDelete->key = alternative->key; + ToDelete = alternative; + } + + if (ToDelete->left == TreeRoot->nil){ + node = ToDelete->right; + RBTreeTransplant(TreeRoot, ToDelete, ToDelete->right); + }else if (ToDelete->right == TreeRoot->nil){ + node = ToDelete->left; + RBTreeTransplant(TreeRoot, ToDelete, ToDelete->left); + } + + if (ToDelete->color == BLACK){ + while (node != TreeRoot->root && node->color == BLACK){ + if (node == node->parent->left){ + RBTreeType *brother = node->parent->right; + + if (brother->color == RED){ + brother->color = BLACK; + brother->parent->color = RED; + RBTreeLeftRotate(TreeRoot, node->parent); + brother = node->parent->right; + } + + if (brother->left->color == BLACK && brother->right->color == BLACK){ + if (brother->parent->color == RED){ + node->parent->color = BLACK; + brother->color = RED; + + break; + }else{ + brother->color = RED; + node = node->parent; + continue; + } + } + + if (brother->right->color == BLACK){ + brother->left->color = BLACK; + brother->color = RED; + RBTreeRightRotate(TreeRoot, brother); + brother = node->parent->right; + } + + brother->color = node->parent->color; + node->parent->color = BLACK; + brother->right->color = BLACK; + RBTreeLeftRotate(TreeRoot, node->parent); + node = TreeRoot->root; + }else{ + RBTreeType *brother = node->parent->left; + if (brother->color == RED){ + brother->color = BLACK; + node->parent->color = RED; + RBTreeRightRotate(TreeRoot, node->parent); + brother = node->parent->left; + } + + if (brother->left->color == BLACK && brother->right->color == BLACK){ + if (brother->parent->color == RED){ + node->parent->color = BLACK; + brother->color = RED; + break; + }else{ + node->parent->color = BLACK; + brother->color = RED; + node = node->parent; + continue; + } + } + + if (brother->left->color == BLACK){ + brother->color = RED; + brother->right->color = BLACK; + brother = node->parent->left; + } + + brother->color = node->parent->color; + node->parent->color = BLACK; + brother->left->color = BLACK; + RBTreeRightRotate(TreeRoot, node->parent); + node = TreeRoot->root; + } + } + node->color = BLACK; + } + + free(ToDelete); + + return TreeRoot; +} + +void RBTreePrePrint(const RBTreeRootType *TreeRoot, RBTreeType *node) +{ + if (TreeRoot->nil == node) + return; + if (node->color == RED) + printf("%3d(R) ", node->key); + else + printf("%3d(B) ", node->key); + RBTreePrePrint(TreeRoot, node->left); + RBTreePrePrint(TreeRoot, node->right); +} + +void RBTreeInPrint(const RBTreeRootType *TreeRoot, RBTreeType *node) +{ + if (TreeRoot->nil == node) + return; + RBTreeInPrint(TreeRoot, node->left); + if (node->color == RED) + printf("%3d(R) ", node->key); + else + printf("%3d(B) ", node->key); + RBTreeInPrint(TreeRoot, node->right); +} + +void RBTreePrint(const RBTreeRootType *TreeRoot) +{ + assert(TreeRoot != NULL); + printf("前序遍历: "); + RBTreePrePrint(TreeRoot, TreeRoot->root); + printf("\n"); + printf("中序遍历: "); + RBTreeInPrint(TreeRoot, TreeRoot->root); + printf("\n"); +} + +void RBTreeTest(void) +{ + RBTreeRootType *TreeRoot = RBTreeInit(); + int i; + int array[10] = { 11, 7, 1, 2, 8, 14, 15, 5, 4 }; + + printf("Test Red Black Tree\n"); + printf("default_key array: "); + for (i = 0; i < 9; i++){ + printf("%d ", array[i]); + RBTreeInsert(TreeRoot, array[i]); + } + printf("\n"); + + // TreeRoot = RBTreeInsert(TreeRoot, 4); + RBTreePrint(TreeRoot); + + RBTreeDelete(TreeRoot, 8); + RBTreeDelete(TreeRoot, 14); + RBTreeDelete(TreeRoot, 7); + RBTreeDelete(TreeRoot, 11); + + RBTreeDelete(TreeRoot, 8); + RBTreePrint(TreeRoot); +} + +PRIV_SHELL_CMD_FUNCTION(RBTreeTest, a red-black tree test sample, PRIV_SHELL_CMD_MAIN_ATTR); + +#endif diff --git a/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.h b/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.h old mode 100644 new mode 100755 index b9592ac82..8763cd6b7 --- a/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.h +++ b/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.h @@ -1,60 +1,62 @@ -/* -* Copyright (c) 2023 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.h -* @brief: a head file of red-black tree structure -* @version: 1.0 -* @author: AIIT XUOS Lab -* @date: 2023/6/23 -*/ -#ifndef REDBLACKTREE_H_ -#define REDBLACKTREE_H_ -#include -#include - -typedef struct RedBlackNode -{ - int key; - struct RedBlackNode *left_child; - struct RedBlackNode *right_child; - struct RedBlackNode *parent; - bool is_red; -} RBNodeType; - -typedef struct RedBlackTree -{ - RBNodeType *root; - RBNodeType *leaf; -} RBTreeType; - -void TestRBTree(void); - -void RBTreeTraversal(RBTreeType *tree, RBNodeType *node); - -void RBTreeLeftRotate(RBTreeType *tree, RBNodeType *current_node); - -void RBTreeRightRotate(RBTreeType *tree, RBNodeType* current_node); - -void InsertFixup(RBTreeType *tree, RBNodeType* current_node); - -void RBTreeInsert(RBTreeType *tree, RBNodeType* new_node); - -void DeleteFixup(RBTreeType *tree, RBNodeType* current_node); - -void RBTreeDelete(RBTreeType *tree, RBNodeType* target_node); - -RBNodeType* FindSuccessor(RBTreeType *tree, RBNodeType* current_node); - -RBNodeType* RBTreeSearch(RBTreeType *tree, int key); - +/* +* Copyright (c) 2023 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.h +* @brief: a head file of red-black tree structure +* @version: 1.0 +* @author: 白痴也有春天 +* @date: 2023/9/11 +*/ +#ifndef TEST_RBTREE_H +#define TEST_RBTREE_H + +// 红黑树 +typedef enum ColorType {RED, BLACK} ColorType; +typedef struct RBTreeType +{ + int key; + struct RBTreeType *left; + struct RBTreeType *right; + struct RBTreeType *parent; + ColorType color; +}RBTreeType; + +typedef struct RBTreeRootType +{ + struct RBTreeType *root; + struct RBTreeType *nil; +}RBTreeRootType; + + +RBTreeRootType *RBTreeInit(void); + +static void RBTreeHandleReorient(RBTreeRootType *TreeRoot, RBTreeType *node, int key); + +void RBTreeTransplant(RBTreeRootType *TreeRoot, RBTreeType *node, RBTreeType *child); + +static void RBTreeLeftRotate(RBTreeRootType *TreeRoot, RBTreeType *node); +static void RBTreeRightRotate(RBTreeRootType *TreeRoot, RBTreeType *node); + +static RBTreeType *RBTreeFindMin(RBTreeRootType *TreeRoot, RBTreeType *node); +static RBTreeType *RBTreeFindMax(RBTreeRootType *TreeRoot, RBTreeType *node); + +RBTreeRootType *RBTreeInsert(RBTreeRootType *TreeRoot, int key); +RBTreeRootType *RBTreeDelete(RBTreeRootType *TreeRoot, int key); + +void RBTreePrePrint(const RBTreeRootType *TreeRoot, RBTreeType *node); +void RBTreeInPrint(const RBTreeRootType *TreeRoot, RBTreeType *node); +void RBTreePrint(const RBTreeRootType *TreeRoot); + +void RBTreeTest(void); + #endif \ No newline at end of file diff --git a/APP_Framework/Applications/main.c b/APP_Framework/Applications/main.c index b10557a97..e6cd5e94b 100644 --- a/APP_Framework/Applications/main.c +++ b/APP_Framework/Applications/main.c @@ -1,14 +1,14 @@ /* -* 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. -*/ + * 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. + */ #include #include @@ -19,13 +19,13 @@ extern int FrameworkInit(); extern void ApplicationOtaTaskInit(void); int main(void) { - printf("Hello, world! \n"); + // printf("Hello, world! \n"); + // printf("Hello, DHU!\nI'm Tang Liyuan. My student number is 201310424.\n"); + printf("Hello, GitLink! \nWe're \"白痴也有春天\". \n"); FrameworkInit(); #ifdef APPLICATION_OTA ApplicationOtaTaskInit(); #endif - return 0; + return 0; } // int cppmain(void); - -