diff --git a/.vscode/settings.json b/.vscode/settings.json index 9769026..e999045 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,6 +16,7 @@ "config.h": "c", "limits": "c", "*.tcc": "c", - "cstdlib": "c" + "cstdlib": "c", + "string.h": "c" } } \ No newline at end of file diff --git a/include/common.h b/include/common.h index 020475d..1c8841f 100644 --- a/include/common.h +++ b/include/common.h @@ -9,21 +9,4 @@ #include #include -#if RBTREE == 1 -#include "rbtree.h" - typedef prbtree_node_t stack_data_t; - typedef prbtree_node_t queue_data_t; - - typedef int list_data_t; -#elif AVLTREE == 1 -#include "tree.h" - typedef ptree_node_t stack_data_t; - typedef ptree_node_t queue_data_t; -#else - typedef int stack_data_t; - typedef int queue_data_t; - typedef int list_data_t; -#endif - -#endif // _DEMO_H_ - +#endif // _COMMON_H_ diff --git a/include/rbtree.h b/include/rbtree.h deleted file mode 100644 index ed9fe06..0000000 --- a/include/rbtree.h +++ /dev/null @@ -1,49 +0,0 @@ - -#ifndef _RBTREE_H_ -#define _RBTREE_H_ - -#include "common.h" - -#if RBTREE == 1 -typedef int rbtree_data_t; - -typedef struct _rbtree_node_t -{ - rbtree_data_t data; - struct _rbtree_node_t * left; - struct _rbtree_node_t * right; - struct _rbtree_node_t * parent; - uint32_t color; -}rbtree_node_t, *prbtree_node_t; - -typedef struct _rbtree_t -{ - struct _rbtree_node_t * tree; - uint32_t size; -}rbtree_t, *prbtree_t; - - -typedef void (*tree_data_disp_t)(rbtree_data_t data); - - -bool rbtree_init(prbtree_t *head); -void rbtree_destroy(prbtree_t * head); -bool rbtree_empty(prbtree_t head); -void rbtree_clear(prbtree_t head); -uint32_t rbtree_get_size(prbtree_t head); -bool rbtree_insert(prbtree_t head, rbtree_data_t data); -bool rbtree_delete(prbtree_t head, rbtree_data_t data); - - -bool rbtree_get_min(prbtree_t head, rbtree_data_t *data); -bool rbtree_get_max(prbtree_t head, rbtree_data_t *data); -void rbtree_traversal_depth_preorder(prbtree_t head, tree_data_disp_t tree_data_disp); -void rbtree_traversal_depth_inorder(prbtree_t head, tree_data_disp_t tree_data_disp); -void rbtree_traversal_depth_postorder(prbtree_t head, tree_data_disp_t tree_data_disp); -void rbtree_traversal_breadth(prbtree_t head, tree_data_disp_t tree_data_disp); - -// check -bool rbtree_check(prbtree_t head); -#endif - -#endif // _RBTREE_H_ diff --git a/include/unicstl.h b/include/unicstl.h index 00c9819..bf4df7d 100644 --- a/include/unicstl.h +++ b/include/unicstl.h @@ -8,8 +8,8 @@ * @copyright Copyright (c) 2024 * */ -#ifndef _DEMO_H_ -#define _DEMO_H_ +#ifndef _UNICSTL_H_ +#define _UNICSTL_H_ #include "list.h" #include "stack.h" @@ -17,21 +17,4 @@ #include "deque.h" #include "tree.h" -#if RBTREE == 1 -#include "rbtree.h" - typedef prbtree_node_t stack_data_t; - typedef prbtree_node_t queue_data_t; - - typedef int list_data_t; -#elif AVLTREE == 1 -#include "tree.h" - typedef ptree_node_t stack_data_t; - typedef ptree_node_t queue_data_t; -#else - typedef int stack_data_t; - typedef int queue_data_t; - typedef int list_data_t; -#endif - -#endif // _DEMO_H_ - +#endif // _UNICSTL_H_ diff --git a/src/list.c b/src/list.c index b62a90b..5daed1f 100644 --- a/src/list.c +++ b/src/list.c @@ -19,7 +19,7 @@ bool list_append(struct _list* self, void* obj) if (self->size(self) == self->_capacity) { int capacity = self->_capacity * self->_ratio; - void * obj_new = (list_data_t*)realloc(self->obj, capacity * self->_obj_size); + void * obj_new = (void *)realloc(self->obj, capacity * self->_obj_size); if (obj_new == NULL) { return false; @@ -42,7 +42,7 @@ bool list_insert(struct _list* self, int index, void* obj) if (self->size(self) == self->_capacity) { int capacity = self->_capacity * self->_ratio; - void* obj_new = (list_data_t*)realloc(self->obj, capacity * self->_obj_size); + void* obj_new = (void *)realloc(self->obj, capacity * self->_obj_size); if (obj_new == NULL) { return false; diff --git a/src/rbtree.c b/src/rbtree.c deleted file mode 100644 index 9ff6eae..0000000 --- a/src/rbtree.c +++ /dev/null @@ -1,1186 +0,0 @@ - -#include "rbtree.h" -#include "stack.h" -#include "queue.h" - -#if RBTREE == 1 - -// ---------------------------------------- -// rbtree 属性复用 -#define RBT_COLOR(x) ((x)->color) -#define RBT_COLOR_INIT(x) (RBT_COLOR(x) = 0) - -// color <- bit[0] -#define RBT_COLOR_MASK (0x01) -#define RBT_BALCK (0x01) -#define BRT_RED (0x00) - -#define RBT_SET_RED(x) (RBT_COLOR(x) &= ~RBT_BALCK) -#define RBT_SET_BLACK(x) (RBT_COLOR(x) |= RBT_BALCK) -#define RBT_IS_BLACK(x) (((RBT_COLOR(x) & RBT_BALCK) == RBT_BALCK)?true:false) -#define RBT_IS_RED(x) (!RBT_IS_BLACK(x)) -#define RBT_COLOR_ASSIGN(a,b) (RBT_COLOR(a) = RBT_COLOR(b)) - -// ---------------------------------------- -// visited node <- bit[1:2] -#define RBT_VISIT_FLAG_MASK (0x06) -#define RBT_VISIT_FLAG_LEFT (0x04) -#define RBT_VISIT_FLAG_RIGHT (0x02) - -#define RBT_VISIT_CLR(x) (RBT_COLOR(x) &= ~RBT_VISIT_FLAG_MASK) -#define RBT_VISIT_LEFT(x) (RBT_COLOR(x) |= RBT_VISIT_FLAG_LEFT) -#define RBT_VISIT_RIGHT(x) (RBT_COLOR(x) |= RBT_VISIT_FLAG_RIGHT) -#define RBT_IS_VISITED_LEFT(x) (((RBT_COLOR(x) & RBT_VISIT_FLAG_LEFT) == RBT_VISIT_FLAG_LEFT)?\ - true:false) -#define RBT_IS_VISITED_RIGHT(x) (((RBT_COLOR(x) & RBT_VISIT_FLAG_RIGHT) == RBT_VISIT_FLAG_RIGHT)?\ - true:false) - - - -/** - * 函数声明 - */ -static bool rbtree_insert_fixup(prbtree_t head, prbtree_node_t tree); -static bool rbtree_delete_fixup(prbtree_t head, prbtree_node_t tree); - - -bool rbtree_init(prbtree_t *head) -{ - *head = (prbtree_t)malloc(sizeof(rbtree_t)); - if (*head == NULL) - { - return false; - } - (*head)->tree = NULL; - (*head)->size = 0; - return true; -} - -void rbtree_destroy(prbtree_t * head) -{ - if (*head != NULL) - { - rbtree_clear(*head); - free(*head); - *head = NULL; - } -} - -bool rbtree_empty(prbtree_t head) -{ - return ((head == NULL) || (head->tree == NULL)) ? true : false; -} - -void rbtree_clear(prbtree_t head) -{ - pqueue_t queue; - prbtree_node_t root; - prbtree_node_t tree_node; - - if ((head == NULL) || head->tree == NULL) - { - return; - } - root = head->tree; - - queue_init(&queue); - queue_in(queue, root); - - while (!queue_empty(queue)) - { - queue_out(queue, &tree_node); - if (tree_node->left != NULL) - { - queue_in(queue, tree_node->left); - } - if (tree_node->right != NULL) - { - queue_in(queue, tree_node->right); - } - - free(tree_node); - tree_node = NULL; - } - - queue_destroy(&queue); - - head->tree = NULL; - head->size = 0; -} - -uint32_t rbtree_get_size(prbtree_t head) -{ - return head->size; -} - -static prbtree_node_t rbtree_find(prbtree_t head, rbtree_data_t data) -{ - prbtree_node_t root; - - if ((head == NULL) || head->tree == NULL) - { - return NULL; - } - root = head->tree; - - while (root != NULL) - { - if (data < root->data) - { - if (root->left != NULL) - { - root = root->left; - } - else - { - return root; - } - } - else if (data > root->data) - { - if (root->right != NULL) - { - root = root->right; - } - else - { - return root; - } - } - else - { - // == - return root; - } - } - - return root; -} - -static prbtree_node_t get_parent_node(prbtree_node_t tree) -{ - if (tree == NULL) - { - return NULL; - } - return tree->parent; -} - -bool rbtree_insert(prbtree_t head, rbtree_data_t data) -{ - prbtree_node_t tree_node; - prbtree_node_t new_node; - - if (head == NULL) - { - return false; - } - - // no root of tree - if (head->tree == NULL) - { - new_node = (prbtree_node_t)malloc(sizeof(rbtree_node_t)); - if (new_node == NULL) - { - return false; - } - new_node->data = data; - new_node->left = NULL; - new_node->right = NULL; - new_node->parent = NULL; // the parent of root is NULL - RBT_COLOR_INIT(new_node); - - head->tree = new_node; - } - else - { - tree_node = rbtree_find(head, data); - if (data < tree_node->data) - { - new_node = (prbtree_node_t)malloc(sizeof(rbtree_node_t)); - if (new_node == NULL) - { - return false; - } - new_node->data = data; - new_node->left = NULL; - new_node->right = NULL; - new_node->parent = tree_node; - RBT_COLOR_INIT(new_node); - - tree_node->left = new_node; - } - else if(data > tree_node->data) - { - new_node = (prbtree_node_t)malloc(sizeof(rbtree_node_t)); - if (new_node == NULL) - { - return false; - } - new_node->data = data; - new_node->left = NULL; - new_node->right = NULL; - new_node->parent = tree_node; - RBT_COLOR_INIT(new_node); - - tree_node->right = new_node; - } - else - { - // 若key相等,正常来说应该替换value值。 - // 这里的代码仅仅是个工程简单工程示例, - // data区就一个数据,因此此处直接忽略。 - return true; - } - } - - rbtree_insert_fixup(head, new_node); - - if (head->size < _UI32_MAX) - { - head->size++; - } - return true; -} - - -static prbtree_node_t rbtree_turn_left(prbtree_node_t tree) -{ - // 以当前节点为中心旋转 - // 注意父节点并不动,只是为了连接新的子节点 - // - prbtree_node_t node_n; // 当前节点 - prbtree_node_t node_nr; // 当前节点的右子节点 - prbtree_node_t node_p; // 当前节点的父节点 - - if (tree == NULL) - { - return NULL; - } - node_n = tree; - node_nr = node_n->right; - node_p = node_n->parent; - - // 1. 更新node_p子节点 - if (node_p != NULL) - { - // not root of tree - if (node_p->left == node_n) - { - node_p->left = node_nr; - } - else - { - node_p->right = node_nr; - } - } - node_nr->parent = node_p; - - // 2. 旋转 - node_n->parent = node_nr; // 不能直接node_p=node_nr,原因你懂的 - node_n->right = node_nr->left; - node_nr->left = node_n; - if (node_n->right != NULL) - { - node_n->right->parent = node_n; - } - - // 3. 返回新的节点 - return node_nr; -} - - -static prbtree_node_t rbtree_turn_right(prbtree_node_t tree) -{ - // 以当前节点为中心旋转 - // 注意父节点并不动,只是为了连接新的子节点 - // - prbtree_node_t node_n; // 当前节点 - prbtree_node_t node_nl; // 当前节点的左子节点 - prbtree_node_t node_p; // 当前节点的父节点 - - if (tree == NULL) - { - return NULL; - } - node_n = tree; - node_nl = node_n->left; - node_p = node_n->parent; - - // 1. 更新node_p子节点 - if (node_p != NULL) - { - // not node_n - if (node_p->left == node_n) - { - node_p->left = node_nl; - } - else - { - node_p->right = node_nl; - } - } - node_nl->parent = node_p; - - // 2. 旋转 - node_n->parent = node_nl; // 不能直接node_p=node_nl,原因你懂的 - node_n->left = node_nl->right; - node_nl->right = node_n; - if (node_n->left != NULL) - { - node_n->left->parent = node_n; - } - - // 3. 返回新的节点 - return node_nl; -} - -static bool rbtree_insert_fixup(prbtree_t head, prbtree_node_t tree) -{ - prbtree_node_t father, grandfather, uncle; - if ((head == NULL) || head->tree == NULL) - { - return false; - } - - if (tree == NULL) - { - return false; - } - - // --------------------------------------- - // case1.根节点不存在,则直接插入黑色节点 - // case2.父节点为黑,插入红色节点皆可 - // (以上两种情况,要结合insert函数理解) - // case3.主要分为三种情况考虑,如下 - // (左右对称,理解了左三,则右三也就不难了) - // ---------------------------------------- - while (tree->parent != NULL && RBT_IS_RED(tree->parent)) - { - father = get_parent_node(tree); - grandfather = get_parent_node(father); - - if (father == grandfather->left) - { - uncle = grandfather->right; - if (uncle != NULL && RBT_IS_RED(uncle)) - { - RBT_SET_BLACK(father); - RBT_SET_BLACK(uncle); - RBT_SET_RED(grandfather); - tree = grandfather; - } - else - { - if (tree == father->right) - { - tree = rbtree_turn_left(father); - RBT_SET_BLACK(tree); - } - else - { - RBT_SET_BLACK(father); - } - RBT_SET_RED(grandfather); - tree = rbtree_turn_right(grandfather); - break; - } - } - else - { - uncle = grandfather->left; - if (uncle != NULL && RBT_IS_RED(uncle)) - { - RBT_SET_BLACK(father); - RBT_SET_BLACK(uncle); - RBT_SET_RED(grandfather); - tree = grandfather; - } - else - { - if (tree == father->left) - { - tree = rbtree_turn_right(father); - RBT_SET_BLACK(tree); - } - else - { - RBT_SET_BLACK(father); - } - RBT_SET_RED(grandfather); - tree = rbtree_turn_left(grandfather); - break; - } - } - } - - if (tree->parent == NULL) - { - head->tree = tree; - RBT_SET_BLACK(head->tree); - } - - return true; -} - -static prbtree_node_t tree_get_node_min(prbtree_node_t tree) -{ - while (tree != NULL) - { - if (tree->left != NULL) - { - tree = tree->left; - } - else - { - return tree; - } - } - return tree; -} - -bool rbtree_delete(prbtree_t head, rbtree_data_t data) -{ - prbtree_node_t tree_node; //当前本该删除的节点 - prbtree_node_t tree_node_del; //实际上被删除的节点 - - if ((head == NULL) || head->tree == NULL) - { - return false; - } - - tree_node = rbtree_find(head, data); - if (tree_node == NULL) - { - return false; - } - - if (tree_node->data != data) - { - // 没有找到该参数 - return false; - } - - if (tree_node->left == NULL && tree_node->right == NULL) - { - tree_node_del = tree_node; - } - else if (tree_node->left != NULL && tree_node->right == NULL) - { - tree_node_del = tree_node->left; - tree_node->data = tree_node_del->data; - } - else if (tree_node->left == NULL && tree_node->right != NULL) - { - tree_node_del = tree_node->right; - tree_node->data = tree_node_del->data; - } - else - { - // 双子都在,则查找后继节点 - tree_node_del = tree_get_node_min(tree_node->right); - - tree_node->data = tree_node_del->data; - if (tree_node_del->right != NULL) - { - // 必红 - tree_node_del->data = tree_node_del->right->data; - tree_node_del = tree_node_del->right; - } - } - - if (RBT_IS_BLACK(tree_node_del)) - { - rbtree_delete_fixup(head, tree_node_del); - } - - // 从tree中删除 - if (tree_node_del->parent != NULL) - { - if (tree_node_del == tree_node_del->parent->left) - { - tree_node_del->parent->left = NULL; - } - else - { - tree_node_del->parent->right = NULL; - } - } - else - { - // 若为根节点 - head->tree = NULL; - } - // 释放内存 - free(tree_node_del); - - if (head->size > 0) - { - head->size--; - } - return true; -} - -static bool rbtree_delete_fixup(prbtree_t head, prbtree_node_t tree) -{ - prbtree_node_t node_temp = NULL; - prbtree_node_t father, brother; - if ((head == NULL) || head->tree == NULL) - { - return false; - } - - while ((tree->parent != NULL) && RBT_IS_BLACK(tree)) - { - father = get_parent_node(tree); - if (tree == father->left) - { - brother = father->right; - if (RBT_IS_RED(brother)) - { - // 根据rbtree性质,父节点必定为黑, - // 红brother的子节点双黑或者双空 - // case 5 - RBT_SET_BLACK(brother); - RBT_SET_RED(father); - node_temp = rbtree_turn_left(father); - // 节点未删除时平衡,但是删除之后又不平衡了 - // 因此需要继续判断 - } - else if(brother->right != NULL && RBT_IS_RED(brother->right)) - { - // 黑bother存在right节点,并且为红色的情况 - // 父节点颜色未知 - // case 1 (仅右子红)和 case 3(双子红) 本质上一样 - RBT_COLOR_ASSIGN(brother,father); //color(f) -> color(b) - RBT_SET_BLACK(father); - RBT_SET_BLACK(brother->right); - tree = rbtree_turn_left(father); - // 删除节点之后,肯定平衡了,因此退出 - // 另外,翻转之后,若刚好是根节点。则赋值给tree - // 方便循环外面判断 - break; - } - else if(brother->left != NULL && RBT_IS_RED(brother->left)) - { - // 黑bother仅有left节点,且left为红色,(且rigth不红的情况) - // 父节点颜色未知 - // case 2 - // 注意:这样写代码的话,则必须在case2前先判断case1/case3 - RBT_SET_RED(brother); - RBT_SET_BLACK(brother->left); - node_temp = rbtree_turn_right(brother); - // 随后转化为了case 1 - } - else - { - // 黑brother的子节点为双空或双黑 - // case 4 - if(RBT_IS_BLACK(father)) - { - // 若父节点为黑,则将brother染为红色, - // 但是总体是少了一黑,因此以父节点为tree向上递归 - RBT_SET_RED(brother); - tree = father; - } - else - { - // brother双子空,则表示brother和被删除的节点平衡 - // 因此直接转换颜色即可 - RBT_SET_RED(brother); - RBT_SET_BLACK(father); - // 删除节点之后,肯定平衡了,因此退出 - break; - } - } - } - else - { - brother = father->left; - if (RBT_IS_RED(brother)) - { - // 根据rbtree性质,父节点必定为黑, - // 红brother的子节点双黑或者双空 - // case 5 - RBT_SET_BLACK(brother); - RBT_SET_RED(father); - node_temp = rbtree_turn_right(father); - // 节点未删除时平衡,但是删除之后又不平衡了 - // 因此需要继续判断 - } - else if (brother->left != NULL && RBT_IS_RED(brother->left)) - { - // 黑bother存在left节点,并且为红色的情况 - // 父节点颜色未知 - // case 1 (仅右子红)和 case 3(双子红) 本质上一样 - RBT_COLOR_ASSIGN(brother,father); - RBT_SET_BLACK(father); - RBT_SET_BLACK(brother->left); - tree = rbtree_turn_right(father); - // 删除节点之后,肯定平衡了,因此退出 - // 另外,翻转之后,若刚好是根节点。则赋值给tree - // 方便循环外面判断 - break; - } - else if (brother->right != NULL && RBT_IS_RED(brother->right)) - { - // 黑bother存在right节点,且right为红色。(且left不红的情况) - // 父节点颜色未知 - // case 2 - // 注意:这样写代码的话,则必须在case2前先判断case1/case3 - RBT_SET_RED(brother); - RBT_SET_BLACK(brother->right); - node_temp = rbtree_turn_left(brother); - // 随后转化为了 case 1 - } - else - { - // 黑brother的子节点为双空或双黑 - // case 4 - if(RBT_IS_BLACK(father)) - { - // 若父节点为黑,则将brother染为红色, - // 但是总体是少了一黑,因此以父节点为tree向上递归 - RBT_SET_RED(brother); - tree = father; - } - else - { - // brother双子空,则表示brother和被删除的节点平衡 - // 因此直接转换颜色即可 - RBT_SET_RED(brother); - RBT_SET_BLACK(father); - // 删除节点之后,肯定平衡了,因此退出 - break; - } - } - } - - // 在处理过程中,防止根节点丢失 - if (node_temp != NULL && node_temp->parent == NULL) - { - head->tree = node_temp; - } - } - - if (tree->parent == NULL) - { - head->tree = tree; - } - - RBT_SET_BLACK(head->tree); - return true; -} - - - -bool rbtree_get_min(prbtree_t head, rbtree_data_t *data) -{ - prbtree_node_t root; - - if ((head == NULL) || head->tree == NULL) - { - return false; - } - root = head->tree; - - while (root != NULL) - { - if (root->left != NULL) - { - root = root->left; - } - else - { - *data = root->data; - return true; - } - } - return false; -} - -bool rbtree_get_max(prbtree_t head, rbtree_data_t *data) -{ - prbtree_node_t root; - if ((head == NULL) || head->tree == NULL) - { - return false; - } - root = head->tree; - - while (root != NULL) - { - if (root->right != NULL) - { - root = root->right; - } - else - { - *data = root->data; - return true; - } - } - return false; -} - -#if 1 -void rbtree_traversal_depth_preorder(prbtree_t head, tree_data_disp_t tree_data_disp) -{ - pstack_t stack; - prbtree_node_t root; - prbtree_node_t tree_node; - - if ((head == NULL) || head->tree == NULL) - { - return; - } - root = head->tree; - - stack_init(&stack); - tree_node = root; - while (!stack_empty(stack) || tree_node != NULL) - { - if (tree_node != NULL) - { - tree_data_disp(tree_node->data); - - stack_push(stack, tree_node); - tree_node = tree_node->left; - } - else - { - stack_pop(stack, &tree_node); - tree_node = tree_node->right; - } - } - - stack_destroy(&stack); -} - -void rbtree_traversal_depth_inorder(prbtree_t head, tree_data_disp_t tree_data_disp) -{ - pstack_t stack; - prbtree_node_t root; - prbtree_node_t tree_node; - - if ((head == NULL) || head->tree == NULL) - { - return; - } - root = head->tree; - - stack_init(&stack); - tree_node = root; - while (!stack_empty(stack) || tree_node != NULL) - { - if (tree_node != NULL) - { - stack_push(stack, tree_node); - tree_node = tree_node->left; - } - else - { - stack_pop(stack, &tree_node); - tree_data_disp(tree_node->data); - tree_node = tree_node->right; - } - } - - stack_destroy(&stack); -} - -void rbtree_traversal_depth_postorder(prbtree_t head, tree_data_disp_t tree_data_disp) -{ - pstack_t stack; - pstack_t stack_disp; - prbtree_node_t root; - prbtree_node_t tree_node; - - if ((head == NULL) || head->tree == NULL) - { - return; - } - root = head->tree; - - stack_init(&stack); - stack_init(&stack_disp); - tree_node = root; - while (!stack_empty(stack) || tree_node != NULL) - { - if (tree_node != NULL) - { - stack_push(stack_disp, tree_node); - - stack_push(stack, tree_node); - tree_node = tree_node->right; - } - else - { - stack_pop(stack, &tree_node); - tree_node = tree_node->left; - } - } - - while (!stack_empty(stack_disp)) - { - stack_pop(stack_disp, &tree_node); - tree_data_disp(tree_node->data); - } - - stack_destroy(&stack); - stack_destroy(&stack_disp); -} -#else -// ------------------------------------------------- -// 方式2 借助了访问标志,不过有个优势,方便计算高度 -// ------------------------------------------------- -void rbtree_traversal_depth_preorder(prbtree_t head, tree_data_disp_t tree_data_disp) -{ - pstack_t stack; - prbtree_node_t root; - prbtree_node_t tree_node; - - if ((head == NULL) || head->tree == NULL) - { - return; - } - root = head->tree; - - stack_init(&stack); - stack_push(stack, root); - tree_data_disp(root->data); - while (!stack_empty(stack)) - { - stack_get_top(stack, &tree_node); - - if (tree_node->left != NULL && !RBT_IS_VISITED_LEFT(tree_node)) - { - RBT_VISIT_LEFT(tree_node); - - stack_push(stack, tree_node->left); - tree_node = tree_node->left; - - tree_data_disp(tree_node->data); - } - else if (tree_node->right != NULL && !RBT_IS_VISITED_RIGHT(tree_node)) - { - RBT_VISIT_RIGHT(tree_node); - - stack_push(stack, tree_node->right); - tree_node = tree_node->right; - - tree_data_disp(tree_node->data); - } - else - { - RBT_VISIT_CLR(tree_node); - stack_pop(stack, &tree_node); - } - } - - stack_destroy(&stack); -} - -void rbtree_traversal_depth_inorder(prbtree_t head, tree_data_disp_t tree_data_disp) -{ - pstack_t stack; - prbtree_node_t root; - prbtree_node_t tree_node; - - if ((head == NULL) || head->tree == NULL) - { - return; - } - root = head->tree; - - stack_init(&stack); - stack_push(stack, root); - while (!stack_empty(stack)) - { - stack_get_top(stack, &tree_node); - - if (tree_node->left != NULL && !RBT_IS_VISITED_LEFT(tree_node)) - { - RBT_VISIT_LEFT(tree_node); - - stack_push(stack, tree_node->left); - tree_node = tree_node->left; - } - else if (tree_node->right != NULL && !RBT_IS_VISITED_RIGHT(tree_node)) - { - RBT_VISIT_RIGHT(tree_node); - - tree_data_disp(tree_node->data); - - stack_push(stack, tree_node->right); - tree_node = tree_node->right; - } - else - { - if (!RBT_IS_VISITED_RIGHT(tree_node)) - { - tree_data_disp(tree_node->data); - } - - RBT_VISIT_CLR(tree_node); - stack_pop(stack, &tree_node); - } - } - - stack_destroy(&stack); -} - -void rbtree_traversal_depth_postorder(prbtree_t head, tree_data_disp_t tree_data_disp) -{ - pstack_t stack; - prbtree_node_t root; - prbtree_node_t tree_node; - - if ((head == NULL) || head->tree == NULL) - { - return; - } - root = head->tree; - - stack_init(&stack); - stack_push(stack, root); - while (!stack_empty(stack)) - { - stack_get_top(stack, &tree_node); - - if (tree_node->left != NULL && !RBT_IS_VISITED_LEFT(tree_node)) - { - RBT_VISIT_LEFT(tree_node); - - stack_push(stack, tree_node->left); - tree_node = tree_node->left; - } - else if (tree_node->right != NULL && !RBT_IS_VISITED_RIGHT(tree_node)) - { - RBT_VISIT_RIGHT(tree_node); - - stack_push(stack, tree_node->right); - tree_node = tree_node->right; - } - else - { - RBT_VISIT_CLR(tree_node); - stack_pop(stack, &tree_node); - - tree_data_disp(tree_node->data); - } - } - - stack_destroy(&stack); -} -#endif - - -void rbtree_traversal_breadth(prbtree_t head, tree_data_disp_t tree_data_disp) -{ - pqueue_t queue; - prbtree_node_t root; - prbtree_node_t tree_node; - - if ((head == NULL) || head->tree == NULL) - { - return; - } - root = head->tree; - - queue_init(&queue); - queue_in(queue, root); - if (root != NULL) - { - while (!queue_empty(queue)) - { - queue_out(queue, &tree_node); - if (tree_node->left != NULL) - { - queue_in(queue, tree_node->left); - } - if (tree_node->right != NULL) - { - queue_in(queue, tree_node->right); - } - - tree_data_disp(tree_node->data); - } - } - - queue_destroy(&queue); -} - - -static bool rbtree_node_check(prbtree_node_t tree_node) -{ - // check - if (tree_node->parent == NULL) - { - if (RBT_IS_RED(tree_node)) - { - return false; - } - } - else - { - if (RBT_IS_RED(tree_node)) - { - if (tree_node->left != NULL && tree_node->right != NULL) - { - if (RBT_IS_RED(tree_node->left) || RBT_IS_RED(tree_node->right)) - { - // error - return false; - } - } - else if (tree_node->left != NULL && tree_node->right == NULL) - { - // error - return false; - } - else if (tree_node->left == NULL && tree_node->right != NULL) - { - // error - return false; - } - else - { - // pass - } - } - else - { - if (tree_node->left != NULL && tree_node->right == NULL) - { - if (RBT_IS_BLACK(tree_node->left)) - { - // error - return false; - } - } - else if (tree_node->left == NULL && tree_node->right != NULL) - { - if (RBT_IS_BLACK(tree_node->right)) - { - // error - return false; - } - } - else - { - // pass - } - } - } - - return true; -} - - -bool rbtree_check(prbtree_t head) -{ - pstack_t stack; - prbtree_node_t root; - prbtree_node_t tree_node; - - bool ret = true; - uint32_t black_cnt = 0, black_cnt_max = 0; - - if ((head == NULL) || head->tree == NULL) - { - // ok - return ret; - } - root = head->tree; - - if (RBT_IS_RED(root)) - { - ret = false; - return ret; - } - else - { - black_cnt++; - if (black_cnt > black_cnt_max) - { - black_cnt_max = black_cnt; - } - } - - stack_init(&stack); - stack_push(stack, root); - while (!stack_empty(stack)) - { - stack_get_top(stack,&tree_node); - - if (tree_node->left != NULL && !RBT_IS_VISITED_LEFT(tree_node)) - { - RBT_VISIT_LEFT(tree_node); - - stack_push(stack, tree_node->left); - tree_node = tree_node->left; - - if (RBT_IS_BLACK(tree_node)) - { - black_cnt++; - if (black_cnt > black_cnt_max) - { - black_cnt_max = black_cnt; - } - } - } - else if (tree_node->right != NULL && !RBT_IS_VISITED_RIGHT(tree_node)) - { - RBT_VISIT_RIGHT(tree_node); - - stack_push(stack, tree_node->right); - tree_node = tree_node->right; - - if (RBT_IS_BLACK(tree_node)) - { - black_cnt++; - if (black_cnt > black_cnt_max) - { - black_cnt_max = black_cnt; - } - } - } - else - { - if (tree_node->left == NULL && tree_node->right == NULL) - { - if (black_cnt != black_cnt_max) - { - ret = false; - goto black_check_exit; - } - } - - RBT_VISIT_CLR(tree_node); - stack_pop(stack, &tree_node); - - if (RBT_IS_BLACK(tree_node)) - { - if (black_cnt > 0) - { - black_cnt--; - } - } - - // check node - if (true != rbtree_node_check(tree_node)) - { - ret = false; - goto black_check_exit; - } - } - } - -black_check_exit: - stack_destroy(&stack); - return ret; -} - -#endif // RBTREE == 1 - diff --git a/test/test.c b/test/test.c index b37dc17..274c408 100644 --- a/test/test.c +++ b/test/test.c @@ -55,7 +55,6 @@ int main() // test_queue(); test_tree(); - // rbtree_test(); } return 0; } diff --git a/test/test_rbtree.c b/test/test_rbtree.c deleted file mode 100644 index 47b078e..0000000 --- a/test/test_rbtree.c +++ /dev/null @@ -1,254 +0,0 @@ - -#include "test.h" - -#if RBTREE_TEST == 1 - -#define TREE_DISP_DEPTH_PRE(tree) {rbtree_traversal_depth_preorder(tree,tree_data_display);printf("\n");} -#define TREE_DISP_DEPTH_IN(tree) {rbtree_traversal_depth_inorder(tree,tree_data_display);printf("\n");} -#define TREE_DISP_DEPTH_POST(tree) {rbtree_traversal_depth_postorder(tree,tree_data_display);printf("\n");} -#define TREE_DISP_BREADTH(tree) {rbtree_traversal_breadth(tree,tree_data_display);printf("\n");} - -// tree display -#define TREE_DISP(tree) TREE_DISP_DEPTH_IN(tree) - -static void tree_data_display(rbtree_data_t data) -{ - printf("%4d ", data); -} - -void rbtree_base(void) -{ - int32_t i = 0; - rbtree_data_t dat[10] = { 5,0,2,4,3,1,8,7,9,6 }; // debug data - rbtree_data_t tmp; - prbtree_t tree = NULL; - - rbtree_init(&tree); - - for (i = 0; i < 10; i++) - { - rbtree_insert(tree, dat[i]); - } - printf("tree : "); - TREE_DISP(tree); - - rbtree_get_min(tree, &tmp); - if (tmp == 0) - { - printf("success -> tree_get_min is %d\n", tmp); - } - else - { - printf("failure -> tree_get_min is %d ?\n", tmp); - } - - rbtree_get_max(tree, &tmp); - if (tmp == 9) - { - printf("success -> tree_get_max is %d\n", tmp); - } - else - { - printf("failure -> tree_get_max is %d ?\n", tmp); - } - - // delete the leaf - rbtree_delete(tree, 6); - printf("del %d: ", 6); - TREE_DISP(tree); - - // delete the node which one child - rbtree_delete(tree, 0); - printf("del %d: ", 0); - TREE_DISP(tree); - - // delete the node which has two nodes - rbtree_delete(tree, 2); - printf("del %d: ", 2); - TREE_DISP(tree); - - // delete the root - rbtree_delete(tree, 4); - printf("del %d: ", 4); - TREE_DISP(tree); - - rbtree_clear(tree); - printf("success -> tree_clear success!\n"); - if (rbtree_empty(tree)) - { - printf("success -> the tree is empty\n"); - } - else - { - printf("failure -> the tree is not empty\n"); - } - - if (!rbtree_delete(tree, 8)) - { - printf("success -> tree is empty, so delete failureed!\n"); - } - else - { - printf("failure -> tree is empty, but delete succeed!\n"); - } - - - // ------------------------------------ - // insert again - for (i = 0; i < 10; i++) - { - rbtree_insert(tree, dat[i]); - } - printf("tree : "); - TREE_DISP(tree); - - for (i = 0; i < 10; i++) - { - if (rbtree_delete(tree, i)) - { - printf("del %d: ", i); - TREE_DISP(tree); - } - } - - if (rbtree_empty(tree)) - { - printf("success -> the tree is empty\n"); - } - else - { - printf("failure -> the tree is not empty\n"); - } - - rbtree_destroy(&tree); - if (!rbtree_insert(tree, dat[0])) - { - printf("success -> after tree destroyed, tree_insert failureed!\n"); - } - - if (!rbtree_get_min(tree, &tmp)) - { - printf("success -> after tree destroyed, tree_get_min failured!\n"); - } - - if (!rbtree_get_max(tree, &tmp)) - { - printf("success -> after tree destroyed, tree_get_max failured!\n"); - } - - printf("----------------------------------------\n"); -} - -void rbtree_random_insert_test(void) -{ -#define INSERT_NUM_MAX 128 - uint32_t i = 0; - const uint32_t len = INSERT_NUM_MAX; - rbtree_data_t dat[INSERT_NUM_MAX]; - rbtree_data_t dd[] = { 5,0,2,4,3,1,8,7,9,6 }; - - prbtree_t tree = NULL; - rbtree_init(&tree); - - printf("orig_data:\n"); - srand((uint32_t)time(0)); - for (i = 0; i < len; i++) - { - dat[i] = rand() % len; - // dat[i] = dd[i]; - printf("%d,", dat[i]); - } - printf("\n----------------------------------------\n"); - - for (i = 0; i < len; i++) - { - // printf("insert %-04d\n", dat[i]); - rbtree_insert(tree, dat[i]); - // TREE_DISP(tree); - - if (true != rbtree_check(tree)) - { - printf("failure -> insert\n"); - SYSTEM_PAUSE(); - } - } - - TREE_DISP_DEPTH_PRE(tree); - TREE_DISP_DEPTH_IN(tree); - TREE_DISP_DEPTH_POST(tree); - TREE_DISP_BREADTH(tree); - - rbtree_destroy(&tree); -} - - -void rbtree_random_delete_test(void) -{ -#define MAX_NUMBER 128 - uint32_t i = 0; - const uint32_t len = MAX_NUMBER; - rbtree_data_t dat[MAX_NUMBER]; - rbtree_data_t dd[] = { 22,12,5,2,0,21,5,22,30,11,6,18,22,5,7,17,13,13,24,13,14,1,20,12,22,24,19,14,17,13,24 }; - - prbtree_t tree = NULL; - rbtree_init(&tree); - static uint8_t srand_flag = 0; - - if (srand_flag == 0) - { - srand((uint32_t)time(0)); - srand_flag = 1; - } - printf("orig_data:\n"); - for (i = 0; i < len; i++) - { - dat[i] = rand() % len; - // dat[i] = dd[i]; - printf("%d,", dat[i]); - } - printf("\n----------------------------------------\n"); - - for (i = 0; i < len; i++) - { - rbtree_insert(tree, dat[i]); - - if (true != rbtree_check(tree)) - { - printf("failure -> insert\n"); - SYSTEM_PAUSE(); - } - } - // TREE_DISP(tree); - printf("----------------------------------------\n"); - - for (i = 0; i < len; i++) - { - // printf("delete %-04d\n", dat[i]); - rbtree_delete(tree, dat[i]); - // TREE_DISP(tree); - if (true != rbtree_check(tree)) - { - printf("failure -> delete\n"); - SYSTEM_PAUSE(); - } - } - printf("----------------------------------------\n"); - - if (rbtree_empty(tree)) - { - printf("success -> the tree is empty\n"); - } - - rbtree_destroy(&tree); -} - - -void rbtree_test(void) -{ - // rbtree_base(); - // rbtree_random_insert_test(); - rbtree_random_delete_test(); -} - -#endif -