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..c8463cc60 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_rbtree/test_rbtree.c @@ -0,0 +1,561 @@ +/* +* 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/23 +*/ +#include +#include +#include"test_rbtree.h" +#include +#include +#ifdef ADD_XIZI_FEATURES + +// 红黑树节点颜色 +#define RED true +#define BLACK false + +// 初始化红黑树 +void InitializeRBTree(RBTreeType* tree) { + tree->root = NULL; // 设置树根为空 + tree->leaf = (RBNodeType*)malloc(sizeof(RBNodeType)); // 分配叶子节点内存 + tree->leaf->is_red = BLACK; // 设置叶子节点为黑色 + tree->leaf->left_child = NULL; + tree->leaf->right_child = NULL; + tree->leaf->parent = NULL; + tree->leaf->key = -1; // 叶子节点的键值设置为特殊值 +} + +// 释放红黑树内存 +void FreeRBTree(RBTreeType* tree, RBNodeType* node) { + if (node == NULL || node == tree->leaf) { + return; + } + FreeRBTree(tree, node->left_child); + FreeRBTree(tree, node->right_child); + free(node); +} + +// 辅助函数 +static RBNodeType* RBTreeMinimum(RBNodeType* node) { + while (node->left_child != NULL) { + node = node->left_child; + } + return node; +} + +static void RBTreeTransplant(RBTreeType* tree, RBNodeType* old_node, RBNodeType* new_node) { + if (old_node->parent == tree->leaf) { + tree->root = new_node; + } else if (old_node == old_node->parent->left_child) { + old_node->parent->left_child = new_node; + } else { + old_node->parent->right_child = new_node; + } + if (new_node != NULL) { + new_node->parent = old_node->parent; + } +} + +// 左旋转操作 +static void RBTreeLeftRotate(RBTreeType* tree, RBNodeType* current_node) { + RBNodeType* right_child = current_node->right_child; + current_node->right_child = right_child->left_child; + if (right_child->left_child != tree->leaf) { + right_child->left_child->parent = current_node; + } + right_child->parent = current_node->parent; + if (current_node->parent == tree->leaf) { + tree->root = right_child; + } else if (current_node == current_node->parent->left_child) { + current_node->parent->left_child = right_child; + } else { + current_node->parent->right_child = right_child; + } + right_child->left_child = current_node; + current_node->parent = right_child; +} + + +// 右旋转操作 +static void RBTreeRightRotate(RBTreeType* tree, RBNodeType* current_node) { + RBNodeType* left_child = current_node->left_child; + current_node->left_child = left_child->right_child; + if (left_child->right_child != tree->leaf) { + left_child->right_child->parent = current_node; + } + left_child->parent = current_node->parent; + if (current_node->parent == tree->leaf) { + tree->root = left_child; + } else if (current_node == current_node->parent->right_child) { + current_node->parent->right_child = left_child; + } else { + current_node->parent->left_child = left_child; + } + left_child->right_child = current_node; + current_node->parent = left_child; +} + +// 插入修复函数 +static void InsertFixup(RBTreeType* tree, RBNodeType* current_node) { + while (current_node->parent->is_red) { + if (current_node->parent == current_node->parent->parent->left_child) { + RBNodeType* uncle = current_node->parent->parent->right_child; + if (uncle->is_red) { + current_node->parent->is_red = BLACK; + uncle->is_red = BLACK; + current_node->parent->parent->is_red = RED; + current_node = current_node->parent->parent; + } else { + if (current_node == current_node->parent->right_child) { + current_node = current_node->parent; + RBTreeLeftRotate(tree, current_node); + } + current_node->parent->is_red = BLACK; + current_node->parent->parent->is_red = RED; + RBTreeRightRotate(tree, current_node->parent->parent); + } + } else { + // 对称的情况 + RBNodeType* uncle = current_node->parent->parent->left_child; + if (uncle->is_red) { + current_node->parent->is_red = BLACK; + uncle->is_red = BLACK; + current_node->parent->parent->is_red = RED; + current_node = current_node->parent->parent; + } else { + if (current_node == current_node->parent->left_child) { + current_node = current_node->parent; + RBTreeRightRotate(tree, current_node); + } + current_node->parent->is_red = BLACK; + current_node->parent->parent->is_red = RED; + RBTreeLeftRotate(tree, current_node->parent->parent); + } + } + } + tree->root->is_red = BLACK; +} + +// 插入操作 +void RBTreeInsert(RBTreeType* tree, RBNodeType* new_node) { + RBNodeType* current_node = tree->root; + RBNodeType* parent_node = tree->leaf; + + // 找到插入位置 + while (current_node != tree->leaf) { + //printf("dao xun huan fou\n"); + parent_node = current_node; + if (new_node->key < current_node->key) { + current_node = current_node->left_child; + } else { + current_node = current_node->right_child; + } + } + //printf("chu xun huan fou\n"); + new_node->parent = parent_node; + + if (parent_node == tree->leaf) { + tree->root = new_node; + } else if (new_node->key < parent_node->key) { + parent_node->left_child = new_node; + } else { + parent_node->right_child = new_node; + } + + new_node->left_child = tree->leaf; + new_node->right_child = tree->leaf; + new_node->is_red = RED; + //printf("dao xiu fu fou\n"); + InsertFixup(tree, new_node); +} +/* +// 删除修复函数 +static void DeleteFixup(RBTreeType* tree, RBNodeType* current_node) { + while (current_node != tree->root && current_node->is_red == BLACK) { + if (current_node == current_node->parent->left_child) { + RBNodeType* sibling = current_node->parent->right_child; + if (sibling->is_red) { + sibling->is_red = BLACK; + current_node->parent->is_red = RED; + RBTreeLeftRotate(tree, current_node->parent); + sibling = current_node->parent->right_child; + } + if (sibling->left_child->is_red == BLACK && sibling->right_child->is_red == BLACK) { + sibling->is_red = RED; + current_node = current_node->parent; + } else { + if (sibling->right_child->is_red == BLACK) { + sibling->left_child->is_red = BLACK; + sibling->is_red = RED; + RBTreeRightRotate(tree, sibling); + sibling = current_node->parent->right_child; + } + sibling->is_red = current_node->parent->is_red; + current_node->parent->is_red = BLACK; + sibling->right_child->is_red = BLACK; + RBTreeLeftRotate(tree, current_node->parent); + current_node = tree->root; + } + } else { + // 对称的情况 + RBNodeType* sibling = current_node->parent->left_child; + if (sibling->is_red) { + sibling->is_red = BLACK; + current_node->parent->is_red = RED; + RBTreeRightRotate(tree, current_node->parent); + sibling = current_node->parent->left_child; + } + if (sibling->right_child->is_red == BLACK && sibling->left_child->is_red == BLACK) { + sibling->is_red = RED; + current_node = current_node->parent; + } else { + if (sibling->left_child->is_red == BLACK) { + sibling->right_child->is_red = BLACK; + sibling->is_red = RED; + RBTreeLeftRotate(tree, sibling); + sibling = current_node->parent->left_child; + } + sibling->is_red = current_node->parent->is_red; + current_node->parent->is_red = BLACK; + sibling->left_child->is_red = BLACK; + RBTreeRightRotate(tree, current_node->parent); + current_node = tree->root; + } + } + } + current_node->is_red = BLACK; +} + +// 删除节点 +void RBTreeDelete(RBTreeType* tree, RBNodeType* target_node) { + RBNodeType* current_node = target_node; + RBNodeType* temp_node; + bool original_color = current_node->is_red; + + if (target_node->left_child == tree->leaf) { + temp_node = target_node->right_child; + RBTreeTransplant(tree, target_node, target_node->right_child); + } else if (target_node->right_child == tree->leaf) { + temp_node = target_node->left_child; + RBTreeTransplant(tree, target_node, target_node->left_child); + } else { + current_node = RBTreeMinimum(target_node->right_child); + original_color = current_node->is_red; + temp_node = current_node->right_child; + if (current_node->parent == target_node) { + temp_node->parent = current_node; + } else { + RBTreeTransplant(tree, current_node, current_node->right_child); + current_node->right_child = target_node->right_child; + current_node->right_child->parent = current_node; + } + RBTreeTransplant(tree, target_node, current_node); + current_node->left_child = target_node->left_child; + current_node->left_child->parent = current_node; + current_node->is_red = target_node->is_red; + } + + if (original_color == BLACK) { + DeleteFixup(tree, temp_node); + } + free(target_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); +} +/* +// 查找后继节点 +RBNodeType* FindSuccessor(RBTreeType* tree, RBNodeType* current_node) { + if (current_node->right_child != tree->leaf) { + return RBTreeMinimum(current_node->right_child); + } + RBNodeType* parent_node = current_node->parent; + while (parent_node != tree->leaf && current_node == parent_node->right_child) { + current_node = parent_node; + parent_node = parent_node->parent; + } + return parent_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; +} + +// 中序遍历红黑树 +static void RBTreeInorderTraversal(RBTreeType* tree, RBNodeType* node) { + if (node != tree->leaf) { + RBTreeInorderTraversal(tree, node->left_child); + printf("%d(%s) ", node->key, node->is_red ? "RED" : "BLACK"); + RBTreeInorderTraversal(tree, node->right_child); + } +} + +// 对外提供的遍历接口 +void RBTreeTraversal(RBTreeType* tree) { + RBTreeInorderTraversal(tree, tree->root); + printf("\n"); +} + +// 在红黑树中查找指定键值的节点 +RBNodeType* RBTreeSearch(RBTreeType* tree, int key) { + RBNodeType* current_node = tree->root; + while (current_node != tree->leaf) { + if (key == current_node->key) { + return current_node; + } else if (key < current_node->key) { + current_node = current_node->left_child; + } else { + current_node = current_node->right_child; + } + } + return NULL; +} + +/* +// 测试函数 +void TestRBTree(void) { + RBTreeType tree; + InitializeRBTree(&tree); // 初始化红黑树 + int keys[] = {50, 30, 70, 20, 40, 60, 80, 10, 25, 35, 45, 55, 65, 75, 90, 5, 15, 28, 38, 48}; + + for (int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) { + RBNodeType* new_node = (RBNodeType*)malloc(sizeof(RBNodeType)); + if (new_node == NULL) { + // 处理内存分配失败的情况 + fprintf(stderr, "Error: Memory allocation failed.\n"); + } + new_node->left_child = NULL; + new_node->right_child = NULL; + new_node->parent = NULL; + new_node->is_red = true; + new_node->key = keys[i]; + printf("charuqian\n "); + RBTreeInsert(&tree, new_node); +} + + printf("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n "); + printf("Inorder Traversal: "); + RBTreeTraversal(&tree); + + printf("Enter key to search and delete (Ctrl+C to exit):\n"); + int key; + while (1) { + printf("Enter key: "); + if (scanf("%d", &key) != 1) { + printf("Invalid input. Please enter a valid integer.\n"); + continue; + } + + RBNodeType* found_node = RBTreeSearch(&tree, key); + if (found_node != NULL) { + printf("Key %d found. Parent: %d, Left: %d, Right: %d\n", key, + found_node->parent != NULL ? found_node->parent->key : -1, + found_node->left_child != NULL ? found_node->left_child->key : -1, + found_node->right_child != NULL ? found_node->right_child->key : -1); + RBTreeDelete(&tree, found_node); + printf("Key %d deleted\n", key); + printf("Inorder Traversal: "); + RBTreeTraversal(&tree); + } else { + printf("Key %d not found\n", key); + } + } + + // 释放红黑树内存 + FreeRBTree(&tree, tree.root); + free(tree.leaf); +} +*/ +void TestRBTree(void) +{ + int default_key[] = {50, 30, 70, 20, 40, 60, 80, 10, 25, 35, 45, 55, 65, 75, 90, 5, 15, 28, 38, 48}; + 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: "); + RBTreeTraversal(tree); + int key; + while (1) { + printf("Enter key: "); + if (scanf("%d", &key) != 1) { + printf("Invalid input. Please enter a valid integer.\n"); + continue; + } + if (key==-1||tree==NULL) + { + break; + } + + RBNodeType* found_node = RBTreeSearch(tree, key); + if (found_node != NULL) { + printf("Key %d found. Parent: %d, Left: %d, Right: %d\n", key, + found_node->parent != NULL ? found_node->parent->key : -1, + found_node->left_child != NULL ? found_node->left_child->key : -1, + found_node->right_child != NULL ? found_node->right_child->key : -1); + RBTreeDelete(tree, found_node); + printf("Key %d deleted\n", key); + printf("Inorder Traversal: "); + RBTreeTraversal(tree); + } else { + printf("Key %d not found\n", key); + } + } +// 释放红黑树内存 + FreeRBTree(tree, tree->root); + free(tree->leaf); +} + +PRIV_SHELL_CMD_FUNCTION(TestRBTree, a red-black tree test sample, PRIV_SHELL_CMD_MAIN_ATTR); + +#endif \ No newline at end of file