mirror of
https://gitee.com/apaki/unicstl.git
synced 2025-07-03 23:56:54 +08:00
1525 lines
36 KiB
C
1525 lines
36 KiB
C
/**
|
||
* @file tree.c
|
||
* @author wenjf (Orig5826@163.com)
|
||
* @brief
|
||
* @version 0.1
|
||
* @date 2024-06-23
|
||
*
|
||
* @copyright Copyright (c) 2024
|
||
*
|
||
*/
|
||
#include "tree.h"
|
||
#include "queue.h"
|
||
#include "stack.h"
|
||
|
||
// #define TREE_RECURSIVE_ENABLED
|
||
static struct _tree_node* tree_node_new(struct _tree* self, void* obj)
|
||
{
|
||
assert(self != NULL);
|
||
|
||
void* obj_new = malloc(self->_obj_size);
|
||
if (obj_new == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
memmove(obj_new, obj, self->_obj_size);
|
||
|
||
struct _tree_node* node_new = (struct _tree_node*)malloc(sizeof(struct _tree_node));
|
||
if (node_new == NULL)
|
||
{
|
||
free(obj_new);
|
||
return NULL;
|
||
}
|
||
node_new->obj = obj_new;
|
||
node_new->parent = NULL;
|
||
node_new->left = NULL;
|
||
node_new->right = NULL;
|
||
node_new->balance = 0;
|
||
|
||
return node_new;
|
||
}
|
||
|
||
static void tree_node_free(struct _tree_node** node)
|
||
{
|
||
if (node != NULL && (*node) != NULL)
|
||
{
|
||
if ((*node)->obj != NULL)
|
||
{
|
||
free((*node)->obj);
|
||
}
|
||
free(*node);
|
||
*node = NULL;
|
||
}
|
||
}
|
||
|
||
static uint32_t tree_height_node(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
#ifdef TREE_RECURSIVE_ENABLED
|
||
assert(self != NULL);
|
||
if (root == NULL)
|
||
{
|
||
return 0;
|
||
}
|
||
uint32_t left_height = tree_height_node(self, root->left);
|
||
uint32_t right_height = tree_height_node(self, root->right);
|
||
return (left_height > right_height) ? (left_height + 1) : (right_height + 1);
|
||
#else
|
||
assert(self != NULL);
|
||
if (root == NULL)
|
||
{
|
||
return 0;
|
||
}
|
||
uint32_t height = 0;
|
||
uint32_t count_cur_level = 0;
|
||
uint32_t count_next_level = 0;
|
||
|
||
struct _tree_node* node = root;
|
||
queue_t queue = queue_new(sizeof(struct _tree_node*));
|
||
|
||
queue->push(queue, &node);
|
||
while (!queue->empty(queue))
|
||
{
|
||
queue->pop(queue, &node);
|
||
if (node->left != NULL)
|
||
{
|
||
queue->push(queue, &node->left);
|
||
}
|
||
if (node->right != NULL)
|
||
{
|
||
queue->push(queue, &node->right);
|
||
}
|
||
|
||
if (count_cur_level == count_next_level)
|
||
{
|
||
count_next_level = queue->size(queue);
|
||
height++;
|
||
count_cur_level = 1;
|
||
}
|
||
else
|
||
{
|
||
count_cur_level++;
|
||
}
|
||
}
|
||
queue_free(&queue);
|
||
return height;
|
||
#endif
|
||
}
|
||
|
||
static void tree_set_balance(struct _tree* self, struct _tree_node* node)
|
||
{
|
||
assert(self != NULL);
|
||
if (node == NULL)
|
||
{
|
||
return;
|
||
}
|
||
node->balance = (int32_t)(tree_height_node(self, node->right) - tree_height_node(self, node->left));
|
||
}
|
||
|
||
static struct _tree_node* tree_turn_left(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
assert(root != NULL);
|
||
struct _tree_node* node = root->right;
|
||
if (node == NULL)
|
||
{
|
||
return root;
|
||
}
|
||
|
||
if (root->parent == NULL)
|
||
{
|
||
self->_root = node; // step1
|
||
}
|
||
else
|
||
{
|
||
if (root->parent->left == root)
|
||
{
|
||
root->parent->left = node; // step1
|
||
}
|
||
else if (root->parent->right == root)
|
||
{
|
||
root->parent->right = node; // setp1
|
||
}
|
||
}
|
||
node->parent = root->parent; // step2
|
||
root->parent = node; // step3
|
||
|
||
root->right = node->left; // step4
|
||
if (node->left != NULL)
|
||
{
|
||
node->left->parent = root; // step5
|
||
}
|
||
node->left = root; // step6
|
||
|
||
tree_set_balance(self, root);
|
||
tree_set_balance(self, node);
|
||
return node;
|
||
}
|
||
|
||
static struct _tree_node* tree_turn_right(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
assert(root != NULL);
|
||
struct _tree_node* node = root->left;
|
||
if (node == NULL)
|
||
{
|
||
return root;
|
||
}
|
||
|
||
if (root->parent == NULL)
|
||
{
|
||
self->_root = node; // step1
|
||
}
|
||
else
|
||
{
|
||
if (root->parent->left == root)
|
||
{
|
||
root->parent->left = node; // step1
|
||
}
|
||
else if (root->parent->right == root)
|
||
{
|
||
root->parent->right = node; // setp1
|
||
}
|
||
}
|
||
node->parent = root->parent; // step2
|
||
root->parent = node; // step3
|
||
|
||
root->left = node->right; // step4
|
||
if (node->right != NULL)
|
||
{
|
||
node->right->parent = root; // step5
|
||
}
|
||
node->right = root; // step6
|
||
|
||
tree_set_balance(self, root);
|
||
tree_set_balance(self, node);
|
||
return node;
|
||
}
|
||
|
||
static struct _tree_node* tree_turn_left_then_right(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
assert(root != NULL);
|
||
struct _tree_node* node = root->left;
|
||
if (node != NULL)
|
||
{
|
||
tree_turn_left(self, node);
|
||
}
|
||
node = tree_turn_right(self, root);
|
||
return node;
|
||
}
|
||
|
||
static struct _tree_node* tree_turn_right_then_left(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
assert(root != NULL);
|
||
struct _tree_node* node = root->right;
|
||
if (node != NULL)
|
||
{
|
||
tree_turn_right(self, node);
|
||
}
|
||
node = tree_turn_left(self, root);
|
||
return node;
|
||
}
|
||
|
||
/**
|
||
* @brief
|
||
*
|
||
* if balance = rigth - left,so
|
||
*
|
||
* | case | root->balance | node->balance | function |
|
||
* | ---- | ------------ | -------------- | -------- |
|
||
* | 1 | 2 | >= 0 | left rotation
|
||
* | 2 | 2 | < 0 | first right rotation, then left rotation
|
||
* | 3 | -2 | <= 0 | right rotation
|
||
* | 4 | -2 | > 0 | forth left rotation, then right rotation
|
||
*
|
||
* @param self
|
||
* @return true
|
||
* @return false
|
||
*/
|
||
static bool tree_avl_rebalance(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
#ifdef TREE_RECURSIVE_ENABLED
|
||
assert(self != NULL);
|
||
if (root == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
if (root->left == NULL && root->right == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
tree_set_balance(self, root);
|
||
int balance = root->balance;
|
||
if (balance == 2)
|
||
{
|
||
if (root->right->balance >= 0)
|
||
{
|
||
root = tree_turn_left(self, root);
|
||
}
|
||
else
|
||
{
|
||
root = tree_turn_right_then_left(self, root);
|
||
}
|
||
}
|
||
else if (balance == -2)
|
||
{
|
||
if (root->left->balance <= 0)
|
||
{
|
||
root = tree_turn_right(self, root);
|
||
}
|
||
else
|
||
{
|
||
root = tree_turn_left_then_right(self, root);
|
||
}
|
||
}
|
||
|
||
if (root->parent != NULL)
|
||
{
|
||
tree_avl_rebalance(self, root->parent);
|
||
}
|
||
else
|
||
{
|
||
self->_root = root;
|
||
}
|
||
return true;
|
||
|
||
#else
|
||
assert(self != NULL);
|
||
if (root == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
if (root->left == NULL && root->right == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
int balance = 0;
|
||
|
||
do
|
||
{
|
||
tree_set_balance(self, root);
|
||
balance = root->balance;
|
||
if (balance == 2)
|
||
{
|
||
if (root->right->balance >= 0)
|
||
{
|
||
root = tree_turn_left(self, root);
|
||
}
|
||
else
|
||
{
|
||
root = tree_turn_right_then_left(self, root);
|
||
}
|
||
}
|
||
else if (balance == -2)
|
||
{
|
||
if (root->left->balance <= 0)
|
||
{
|
||
root = tree_turn_right(self, root);
|
||
}
|
||
else
|
||
{
|
||
root = tree_turn_left_then_right(self, root);
|
||
}
|
||
}
|
||
|
||
// if node become the new root
|
||
if (root->parent == NULL)
|
||
{
|
||
break;
|
||
}
|
||
root = root->parent;
|
||
} while (root != NULL);
|
||
|
||
self->_root = root;
|
||
return true;
|
||
#endif
|
||
}
|
||
|
||
static struct _tree_node* tree_find(struct _tree* self, void* obj)
|
||
{
|
||
assert(self != NULL);
|
||
struct _tree_node* root = self->_root;
|
||
while (root != NULL)
|
||
{
|
||
if (self->compare(obj, root->obj) == 0)
|
||
{
|
||
return root;
|
||
}
|
||
else if (self->compare(obj, root->obj) < 0)
|
||
{
|
||
root = root->left;
|
||
}
|
||
else
|
||
{
|
||
root = root->right;
|
||
}
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
static struct _tree_node* tree_find_min(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
while (root != NULL)
|
||
{
|
||
if (root->left == NULL)
|
||
{
|
||
break;
|
||
}
|
||
root = root->left;
|
||
}
|
||
return root;
|
||
}
|
||
|
||
static struct _tree_node* tree_find_max(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
while (root != NULL)
|
||
{
|
||
if (root->right == NULL)
|
||
{
|
||
break;
|
||
}
|
||
root = root->right;
|
||
}
|
||
return root;
|
||
}
|
||
|
||
/**
|
||
* @brief find the position to insert or find object
|
||
*
|
||
* @param self
|
||
* @param obj
|
||
*/
|
||
struct _tree_node* tree_find_pos(struct _tree* self, void* obj)
|
||
{
|
||
assert(self != NULL);
|
||
assert(self->compare != NULL);
|
||
|
||
struct _tree_node* root = self->_root;
|
||
while (root != NULL)
|
||
{
|
||
if (self->compare(obj, root->obj) < 0)
|
||
{
|
||
if (root->left == NULL)
|
||
{
|
||
break;
|
||
}
|
||
root = root->left;
|
||
}
|
||
else if(self->compare(obj, root->obj) > 0)
|
||
{
|
||
if (root->right == NULL)
|
||
{
|
||
break;
|
||
}
|
||
root = root->right;
|
||
}
|
||
else
|
||
{
|
||
// if obj exist
|
||
break;
|
||
}
|
||
}
|
||
return root;
|
||
}
|
||
|
||
|
||
static bool tree_avl_insert(struct _tree* self, void* obj)
|
||
{
|
||
assert(self != NULL);
|
||
assert(obj != NULL);
|
||
assert(self->compare != NULL);
|
||
|
||
if (self->_root == NULL)
|
||
{
|
||
// if tree is empty
|
||
struct _tree_node* new_node = tree_node_new(self, obj);
|
||
if (new_node == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
self->_root = new_node;
|
||
}
|
||
else
|
||
{
|
||
struct _tree_node* root = tree_find_pos(self, obj);
|
||
if (self->compare(obj, root->obj) == 0)
|
||
{
|
||
// if obj is exist in tree, return false
|
||
return false;
|
||
}
|
||
|
||
struct _tree_node* new_node = tree_node_new(self, obj);
|
||
if (new_node == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
if (self->compare(obj, root->obj) < 0)
|
||
{
|
||
root->left = new_node;
|
||
new_node->parent = root;
|
||
}
|
||
else /*if (self->compare(obj, root->obj) > 0)*/
|
||
{
|
||
root->right = new_node;
|
||
new_node->parent = root;
|
||
}
|
||
|
||
self->_rebalance(self, root);
|
||
}
|
||
|
||
self->_size++;
|
||
return true;
|
||
}
|
||
|
||
static bool tree_avl_delete_single_child(struct _tree* self, struct _tree_node* node)
|
||
{
|
||
assert(self != NULL);
|
||
assert(node != NULL);
|
||
|
||
if (node->parent == NULL)
|
||
{
|
||
if (node->left != NULL)
|
||
{
|
||
node->left->parent = node->parent; // step1 : NULL for root
|
||
self->_root = node->left; // step2
|
||
}
|
||
else if (node->right != NULL)
|
||
{
|
||
node->right->parent = node->parent; // step1 : NULL for root
|
||
self->_root = node->right; // step2
|
||
}
|
||
else
|
||
{
|
||
self->_root = NULL;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (node->parent->left == node)
|
||
{
|
||
if (node->left != NULL)
|
||
{
|
||
node->left->parent = node->parent; // step1
|
||
node->parent->left = node->left; // step2
|
||
}
|
||
else if (node->right != NULL)
|
||
{
|
||
node->right->parent = node->parent; // step1
|
||
node->parent->left = node->right; // step2
|
||
}
|
||
else
|
||
{
|
||
node->parent->left = NULL;
|
||
}
|
||
}
|
||
else if (node->parent->right == node)
|
||
{
|
||
if (node->left != NULL)
|
||
{
|
||
node->left->parent = node->parent; // step1
|
||
node->parent->right = node->left; // step2
|
||
}
|
||
else if (node->right != NULL)
|
||
{
|
||
node->right->parent = node->parent; // step1
|
||
node->parent->right = node->right; // step2
|
||
}
|
||
else
|
||
{
|
||
node->parent->right = NULL;
|
||
}
|
||
}
|
||
|
||
self->_rebalance(self, node->parent);
|
||
}
|
||
tree_node_free(&node);
|
||
return true;
|
||
}
|
||
|
||
static bool tree_avl_delete_double_child(struct _tree* self, struct _tree_node* node)
|
||
{
|
||
assert(self != NULL);
|
||
assert(node != NULL);
|
||
struct _tree_node* tmp = tree_find_min(self, node->right);
|
||
if (tmp != NULL)
|
||
{
|
||
memmove(node->obj, tmp->obj, self->_obj_size);
|
||
tree_avl_delete_single_child(self, tmp);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
static bool tree_avl_delete(struct _tree* self, void* obj)
|
||
{
|
||
assert(self != NULL);
|
||
assert(obj != NULL);
|
||
assert(self->compare != NULL);
|
||
|
||
if (self->empty(self))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
struct _tree_node* node = tree_find(self, obj);
|
||
if (node == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
if ((node->left != NULL) && (node->right != NULL))
|
||
{
|
||
// have two child
|
||
tree_avl_delete_double_child(self, node);
|
||
}
|
||
else
|
||
{
|
||
// have singule child or no child
|
||
tree_avl_delete_single_child(self, node);
|
||
}
|
||
|
||
self->_size--;
|
||
return true;
|
||
}
|
||
|
||
static rbt_color tree_color(struct _tree_node* node)
|
||
{
|
||
assert(node != NULL);
|
||
return node->color;
|
||
}
|
||
|
||
static bool tree_set_color(struct _tree_node* node, rbt_color color)
|
||
{
|
||
assert(node != NULL);
|
||
node->color = color;
|
||
return true;
|
||
}
|
||
|
||
static struct _tree_node* tree_rb_turn_left(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
assert(root != NULL);
|
||
struct _tree_node* node = root->right;
|
||
if (node == NULL)
|
||
{
|
||
return root;
|
||
}
|
||
|
||
if (root->parent == NULL)
|
||
{
|
||
self->_root = node; // step1
|
||
}
|
||
else
|
||
{
|
||
if (root->parent->left == root)
|
||
{
|
||
root->parent->left = node; // step1
|
||
}
|
||
else if (root->parent->right == root)
|
||
{
|
||
root->parent->right = node; // setp1
|
||
}
|
||
}
|
||
node->parent = root->parent; // step2
|
||
root->parent = node; // step3
|
||
|
||
root->right = node->left; // step4
|
||
if (node->left != NULL)
|
||
{
|
||
node->left->parent = root; // step5
|
||
}
|
||
node->left = root; // step6
|
||
return node;
|
||
}
|
||
|
||
static struct _tree_node* tree_rb_turn_right(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
assert(root != NULL);
|
||
struct _tree_node* node = root->left;
|
||
if (node == NULL)
|
||
{
|
||
return root;
|
||
}
|
||
|
||
if (root->parent == NULL)
|
||
{
|
||
self->_root = node; // step1
|
||
}
|
||
else
|
||
{
|
||
if (root->parent->left == root)
|
||
{
|
||
root->parent->left = node; // step1
|
||
}
|
||
else if (root->parent->right == root)
|
||
{
|
||
root->parent->right = node; // setp1
|
||
}
|
||
}
|
||
node->parent = root->parent; // step2
|
||
root->parent = node; // step3
|
||
|
||
root->left = node->right; // step4
|
||
if (node->right != NULL)
|
||
{
|
||
node->right->parent = root; // step5
|
||
}
|
||
node->right = root; // step6
|
||
return node;
|
||
}
|
||
|
||
static bool tree_rb_insert(struct _tree* self, void* obj)
|
||
{
|
||
assert(self != NULL);
|
||
assert(obj != NULL);
|
||
assert(self->compare != NULL);
|
||
|
||
struct _tree_node* new_node = NULL;
|
||
if (self->_root == NULL)
|
||
{
|
||
// if tree is empty
|
||
new_node = tree_node_new(self, obj);
|
||
if (new_node == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
self->_root = new_node;
|
||
}
|
||
else
|
||
{
|
||
struct _tree_node* root = tree_find_pos(self, obj);
|
||
if (self->compare(obj, root->obj) == 0)
|
||
{
|
||
// if obj is exist in tree, return false
|
||
return false;
|
||
}
|
||
|
||
new_node = tree_node_new(self, obj);
|
||
if (new_node == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
if (self->compare(obj, root->obj) < 0)
|
||
{
|
||
root->left = new_node;
|
||
new_node->parent = root;
|
||
}
|
||
else /*if (self->compare(obj, root->obj) > 0)*/
|
||
{
|
||
root->right = new_node;
|
||
new_node->parent = root;
|
||
}
|
||
}
|
||
|
||
self->_rebalance(self, new_node);
|
||
|
||
self->_size++;
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* @brief
|
||
*
|
||
* 以 balance = rigth - left 为标准,调整平衡因子
|
||
*
|
||
* | 情况 | root->balance | node->balance | 调整方式 |
|
||
* | ---- | ------------ | -------------- | -------- |
|
||
* | 1 | 2 | >= 0 | 左旋
|
||
* | 2 | 2 | < 0 | 先右旋后左旋
|
||
* | 3 | -2 | <= 0 | 右旋
|
||
* | 4 | -2 | > 0 | 先左旋后右旋
|
||
*
|
||
* @param self
|
||
* @return true
|
||
* @return false
|
||
*/
|
||
static bool tree_rb_rebalance(struct _tree* self, struct _tree_node* node)
|
||
{
|
||
assert(self != NULL);
|
||
if (node == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
struct _tree_node* father = NULL;
|
||
struct _tree_node* grandfather = NULL;
|
||
struct _tree_node* uncle = NULL;
|
||
|
||
/**
|
||
* @brief 新插入节点为红色,且父节点为红色的情况下,需要调整。
|
||
*
|
||
* 主要考虑前三种情况[1-3],其余三种[4-6]对称操作即可
|
||
*
|
||
* 原则只有一个,那就是想办法维持红黑树性质不变
|
||
*
|
||
* | 情况 | 说明 | 调整方式 |
|
||
* | ---- | --- | -------- |
|
||
* | 0 | 父节点为黑色 | 不用处理
|
||
* | 1 | 父红,爷黑,叔红 | 仅变色即可:父黑,爷红,叔黑
|
||
* | 2 | 父红,爷黑,叔黑 | (若爷孙在同一边)父黑,爷红,爷左/右旋
|
||
* | 3 | 父红,爷黑,叔黑 | (若爷孙在不同边)先父左右旋,将新父变黑,随后爷红,爷左/右旋
|
||
*/
|
||
while (node->parent != NULL && node->parent->color == RBT_RED)
|
||
{
|
||
father = node->parent;
|
||
grandfather = father->parent;
|
||
if (father == grandfather->left)
|
||
{
|
||
uncle = grandfather->right;
|
||
if (uncle != NULL && uncle->color == RBT_RED) // uncle is red
|
||
{
|
||
father->color = RBT_BLACK;
|
||
uncle->color = RBT_BLACK;
|
||
grandfather->color = RBT_RED;
|
||
node = grandfather;
|
||
}
|
||
else // uncle is black
|
||
{
|
||
if (node == father->right)
|
||
{
|
||
node = tree_rb_turn_left(self, father);
|
||
node->color = RBT_BLACK;
|
||
}
|
||
else
|
||
{
|
||
father->color = RBT_BLACK;
|
||
}
|
||
grandfather->color = RBT_RED;
|
||
node = tree_rb_turn_right(self, grandfather);
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
uncle = grandfather->left;
|
||
if (uncle != NULL && uncle->color == RBT_RED) // uncle is red
|
||
{
|
||
father->color = RBT_BLACK;
|
||
uncle->color = RBT_BLACK;
|
||
grandfather->color = RBT_RED;
|
||
node = grandfather;
|
||
}
|
||
else // uncle is black
|
||
{
|
||
if (node == father->left)
|
||
{
|
||
node = tree_rb_turn_right(self, father);
|
||
node->color = RBT_BLACK;
|
||
}
|
||
else
|
||
{
|
||
father->color = RBT_BLACK;
|
||
}
|
||
grandfather->color = RBT_RED;
|
||
node = tree_rb_turn_left(self, grandfather);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (node->parent == NULL)
|
||
{
|
||
self->_root = node;
|
||
node->color = RBT_BLACK;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
static bool tree_rb_delete_fix(struct _tree* self, struct _tree_node* node)
|
||
{
|
||
assert(self != NULL);
|
||
struct _tree_node* father = NULL;
|
||
struct _tree_node* brother = NULL;
|
||
struct _tree_node* tmp = NULL;
|
||
if (node == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// the color of node is black
|
||
while (node->parent != NULL && node->color == RBT_BLACK)
|
||
{
|
||
father = node->parent;
|
||
if (father->left == node)
|
||
{
|
||
brother = father->right;
|
||
if (brother->color == RBT_RED)
|
||
{
|
||
// case 1
|
||
// father is black, brother is red
|
||
// brother has two black children
|
||
// so ...
|
||
brother->color = RBT_BLACK;
|
||
father->color = RBT_RED;
|
||
tmp = tree_rb_turn_left(self, father);
|
||
// After deleting the node, it became unbalanced
|
||
// so convert to case5
|
||
}
|
||
else if (brother->right != NULL && brother->right->color == RBT_RED)
|
||
{
|
||
// case 2
|
||
brother->color = father->color;
|
||
father->color = RBT_BLACK;
|
||
brother->right->color = RBT_BLACK;
|
||
node = tree_rb_turn_left(self, father);
|
||
// After deleting the node, it remains balanced
|
||
break;
|
||
}
|
||
else if (brother->left != NULL && brother->left->color == RBT_RED)
|
||
{
|
||
// case 3
|
||
brother->color = RBT_RED;
|
||
brother->left->color = RBT_BLACK;
|
||
tmp = tree_rb_turn_right(self, brother);
|
||
// Convert to case2
|
||
}
|
||
else
|
||
{
|
||
if (father->color == RBT_BLACK)
|
||
{
|
||
// case 4
|
||
// father is black, brother has no children
|
||
brother->color = RBT_RED;
|
||
node = father;
|
||
// After deleting the node, it became unbalanced
|
||
}
|
||
else
|
||
{
|
||
// case 5
|
||
// father is red, brother has no children
|
||
// if delete the node, it remains balanced
|
||
brother->color = RBT_RED;
|
||
father->color = RBT_BLACK;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// symmetric
|
||
brother = father->left;
|
||
if (brother->color == RBT_RED)
|
||
{
|
||
// case1
|
||
brother->color = RBT_BLACK;
|
||
father->color = RBT_RED;
|
||
tmp = tree_rb_turn_right(self, father);
|
||
}
|
||
else if (brother->left != NULL && brother->left->color == RBT_RED)
|
||
{
|
||
// case2
|
||
brother->color = father->color;
|
||
father->color = RBT_BLACK;
|
||
brother->left->color = RBT_BLACK;
|
||
node = tree_rb_turn_right(self, father);
|
||
break;
|
||
}
|
||
else if (brother->right != NULL && brother->right->color == RBT_RED)
|
||
{
|
||
// case3
|
||
brother->color = RBT_RED;
|
||
brother->right->color = RBT_BLACK;
|
||
tmp = tree_rb_turn_left(self, brother);
|
||
// convert to case2
|
||
}
|
||
else
|
||
{
|
||
if (father->color == RBT_BLACK)
|
||
{
|
||
// case4
|
||
brother->color = RBT_RED;
|
||
node = father;
|
||
}
|
||
else
|
||
{
|
||
// case5
|
||
brother->color = RBT_RED;
|
||
father->color = RBT_BLACK;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (tmp != NULL && tmp->parent == NULL)
|
||
{
|
||
self->_root = tmp;
|
||
}
|
||
}
|
||
|
||
if (node->parent == NULL)
|
||
{
|
||
self->_root = node;
|
||
}
|
||
self->_root->color = RBT_BLACK;
|
||
return true;
|
||
}
|
||
|
||
static bool tree_rb_delete(struct _tree* self, void* obj)
|
||
{
|
||
assert(self != NULL);
|
||
assert(obj != NULL);
|
||
assert(self->compare != NULL);
|
||
|
||
if (self->empty(self))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
struct _tree_node* node = tree_find(self, obj);
|
||
if (node == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
struct _tree_node* tmp = NULL;
|
||
if (node->left == NULL && node->right == NULL)
|
||
{
|
||
tmp = node;
|
||
}
|
||
else if (node->left != NULL && node->right == NULL)
|
||
{
|
||
// node->left must be red
|
||
tmp = node->left;
|
||
memmove(node->obj, tmp->obj, self->_obj_size);
|
||
}
|
||
else if (node->left == NULL && node->right != NULL)
|
||
{
|
||
// node->right must be red
|
||
tmp = node->right;
|
||
memmove(node->obj, tmp->obj, self->_obj_size);
|
||
}
|
||
else
|
||
{
|
||
// 1. find the min node in right subtree
|
||
// 2. replace the node with min node
|
||
// 3. delete the min node
|
||
tmp = tree_find_min(self, node->right);
|
||
memmove(node->obj, tmp->obj, self->_obj_size);
|
||
if (tmp->right != NULL)
|
||
{
|
||
// tmp->right must be red
|
||
memmove(tmp->obj, tmp->right->obj, self->_obj_size);
|
||
tmp = tmp->right;
|
||
}
|
||
}
|
||
|
||
if (tmp->color == RBT_BLACK)
|
||
{
|
||
tree_rb_delete_fix(self, tmp);
|
||
}
|
||
|
||
if (tmp->parent != NULL)
|
||
{
|
||
if (tmp->parent->left == tmp)
|
||
{
|
||
tmp->parent->left = NULL;
|
||
}
|
||
else
|
||
{
|
||
tmp->parent->right = NULL;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
self->_root = NULL;
|
||
}
|
||
|
||
tree_node_free(&tmp);
|
||
self->_size--;
|
||
return true;
|
||
}
|
||
|
||
static bool tree_empty(struct _tree* self)
|
||
{
|
||
assert(self != NULL);
|
||
return !self->size(self);
|
||
}
|
||
|
||
static uint32_t tree_size(struct _tree* self)
|
||
{
|
||
assert(self != NULL);
|
||
return self->_size;
|
||
}
|
||
|
||
static bool tree_clear(struct _tree* self)
|
||
{
|
||
assert(self != NULL);
|
||
if (self->_root == NULL)
|
||
{
|
||
// return false;
|
||
return true;
|
||
}
|
||
|
||
struct _tree_node* node = self->_root;
|
||
queue_t queue = queue_new(sizeof(struct _tree_node*));
|
||
|
||
queue->push(queue, &node);
|
||
while (!queue->empty(queue))
|
||
{
|
||
queue->pop(queue, &node);
|
||
if (node->left != NULL)
|
||
{
|
||
queue->push(queue, &node->left);
|
||
}
|
||
if (node->right != NULL)
|
||
{
|
||
queue->push(queue, &node->right);
|
||
}
|
||
tree_node_free(&node);
|
||
}
|
||
queue_free(&queue);
|
||
self->_root = NULL;
|
||
self->_size = 0;
|
||
return true;
|
||
}
|
||
|
||
static void tree_destory(struct _tree* self)
|
||
{
|
||
assert(self != NULL);
|
||
self->clear(self);
|
||
self->_root = NULL;
|
||
|
||
if (self->stack != NULL)
|
||
{
|
||
stack_free(&self->stack);
|
||
}
|
||
if (self->queue != NULL)
|
||
{
|
||
queue_free(&self->queue);
|
||
}
|
||
}
|
||
|
||
static uint32_t tree_height(struct _tree* self)
|
||
{
|
||
return tree_height_node(self, self->_root);
|
||
}
|
||
|
||
|
||
static bool tree_min(struct _tree* self, void* obj)
|
||
{
|
||
assert(self != NULL);
|
||
struct _tree_node* node = tree_find_min(self, self->_root);
|
||
if (node == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
memmove(obj, node->obj, self->_obj_size);
|
||
return true;
|
||
}
|
||
|
||
static bool tree_max(struct _tree* self, void* obj)
|
||
{
|
||
assert(self != NULL);
|
||
struct _tree_node* node = tree_find_max(self, self->_root);
|
||
if (node == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
memmove(obj, node->obj, self->_obj_size);
|
||
return true;
|
||
}
|
||
|
||
static bool tree_iter_hasnext(struct _iterator* iter)
|
||
{
|
||
assert(iter != NULL);
|
||
assert(iter->_container != NULL);
|
||
|
||
tree_t self = (tree_t)iter->_container;
|
||
if(iter->_index < self->size(self))
|
||
{
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
static const void* tree_iter_next(struct _iterator* iter)
|
||
{
|
||
assert(iter != NULL);
|
||
assert(iter->_container != NULL);
|
||
|
||
tree_t self = (tree_t)iter->_container;
|
||
void *obj = NULL;
|
||
|
||
struct _tree_node* cur_node = iter->_node;
|
||
struct _tree_node* target_node = NULL;
|
||
switch (iter->_order)
|
||
{
|
||
case TREE_DFS_PRE:
|
||
case TREE_DFS_PRE_R:
|
||
{
|
||
struct _tree_node* node = NULL;
|
||
if (iter->_order == TREE_DFS_PRE)
|
||
{
|
||
while (!self->stack->empty(self->stack) || cur_node != NULL)
|
||
{
|
||
if (cur_node != NULL)
|
||
{
|
||
target_node = cur_node;
|
||
|
||
self->stack->push(self->stack, &cur_node);
|
||
cur_node = cur_node->left;
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
self->stack->pop(self->stack, &cur_node);
|
||
cur_node = cur_node->right;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
while (!self->stack->empty(self->stack) || cur_node != NULL)
|
||
{
|
||
if (cur_node != NULL)
|
||
{
|
||
target_node = cur_node;
|
||
|
||
self->stack->push(self->stack, &cur_node);
|
||
cur_node = cur_node->right;
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
self->stack->pop(self->stack, &cur_node);
|
||
cur_node = cur_node->left;
|
||
}
|
||
}
|
||
}
|
||
}break;
|
||
case TREE_DFS_IN:
|
||
case TREE_DFS_IN_R:
|
||
{
|
||
if (iter->_order == TREE_DFS_IN)
|
||
{
|
||
while (!self->stack->empty(self->stack) || cur_node != NULL)
|
||
{
|
||
if (cur_node != NULL)
|
||
{
|
||
self->stack->push(self->stack, &cur_node);
|
||
cur_node = cur_node->left;
|
||
}
|
||
else
|
||
{
|
||
self->stack->pop(self->stack, &cur_node);
|
||
target_node = cur_node;
|
||
|
||
cur_node = cur_node->right;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
while (!self->stack->empty(self->stack) || cur_node != NULL)
|
||
{
|
||
if (cur_node != NULL)
|
||
{
|
||
self->stack->push(self->stack, &cur_node);
|
||
cur_node = cur_node->right;
|
||
}
|
||
else
|
||
{
|
||
self->stack->pop(self->stack, &cur_node);
|
||
target_node = cur_node;
|
||
|
||
cur_node = cur_node->left;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}break;
|
||
case TREE_DFS_POST:
|
||
case TREE_DFS_POST_R:
|
||
{
|
||
if (!self->stack->empty(self->stack))
|
||
{
|
||
self->stack->pop(self->stack, &cur_node);
|
||
target_node = cur_node;
|
||
}
|
||
}break;
|
||
case TREE_BFS:
|
||
case TREE_BFS_R:
|
||
{
|
||
queue_t queue = self->queue;
|
||
if (!queue->empty(queue) && cur_node != NULL)
|
||
{
|
||
queue->pop(queue, &cur_node);
|
||
target_node = cur_node;
|
||
|
||
if (iter->_order == TREE_BFS)
|
||
{
|
||
if (cur_node->left != NULL)
|
||
{
|
||
queue->push(queue, &cur_node->left);
|
||
}
|
||
if (cur_node->right != NULL)
|
||
{
|
||
queue->push(queue, &cur_node->right);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (cur_node->right != NULL)
|
||
{
|
||
queue->push(queue, &cur_node->right);
|
||
}
|
||
if (cur_node->left != NULL)
|
||
{
|
||
queue->push(queue, &cur_node->left);
|
||
}
|
||
}
|
||
}
|
||
}break;
|
||
default:
|
||
{
|
||
}break;
|
||
}
|
||
|
||
iter->_node = cur_node;
|
||
obj = target_node->obj;
|
||
iter->_index += 1;
|
||
return obj;
|
||
}
|
||
|
||
|
||
static iterator_t tree_iter(struct _tree* self, enum _tree_order order)
|
||
{
|
||
assert(self != NULL);
|
||
iterator_t iter = &self->_iter;
|
||
|
||
iter->_container = self;
|
||
iter->_index = 0;
|
||
iter->_node = self->_root;
|
||
iter->_order = order;
|
||
iter->hasnext = tree_iter_hasnext;
|
||
iter->next = tree_iter_next;
|
||
|
||
self->stack->clear(self->stack);
|
||
self->queue->clear(self->queue);
|
||
|
||
switch (iter->_order)
|
||
{
|
||
case TREE_DFS_PRE:
|
||
case TREE_DFS_PRE_R:
|
||
{
|
||
// pass
|
||
}break;
|
||
case TREE_DFS_IN:
|
||
case TREE_DFS_IN_R:
|
||
{
|
||
// pass
|
||
}break;
|
||
case TREE_DFS_POST:
|
||
case TREE_DFS_POST_R:
|
||
{
|
||
struct _tree_node* node = self->_root;
|
||
self->stack->clear(self->stack);
|
||
|
||
stack_t stack = stack_new(sizeof(struct _tree_node*));
|
||
if (iter->_order == TREE_DFS_POST)
|
||
{
|
||
while (!stack->empty(stack) || node != NULL)
|
||
{
|
||
if (node != NULL)
|
||
{
|
||
self->stack->push(self->stack, &node);
|
||
|
||
stack->push(stack, &node);
|
||
node = node->right;
|
||
}
|
||
else
|
||
{
|
||
stack->pop(stack, &node);
|
||
node = node->left;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
while (!stack->empty(stack) || node != NULL)
|
||
{
|
||
if (node != NULL)
|
||
{
|
||
self->stack->push(self->stack, &node);
|
||
|
||
stack->push(stack, &node);
|
||
node = node->left;
|
||
}
|
||
else
|
||
{
|
||
stack->pop(stack, &node);
|
||
node = node->right;
|
||
}
|
||
}
|
||
}
|
||
stack_free(&stack);
|
||
}break;
|
||
case TREE_BFS:
|
||
case TREE_BFS_R:
|
||
{
|
||
// pass
|
||
self->queue->push(self->queue, &self->_root);
|
||
}break;
|
||
default:
|
||
{
|
||
}break;
|
||
}
|
||
|
||
return iter;
|
||
}
|
||
|
||
static bool tree_avl_init(struct _tree* self, uint32_t obj_size)
|
||
{
|
||
assert(self != NULL);
|
||
|
||
// -------------------- private --------------------
|
||
self->_obj_size = obj_size;
|
||
self->_size = 0;
|
||
// self->_capacity = 64;
|
||
// self->_ratio = 2;
|
||
|
||
self->_root = NULL;
|
||
|
||
self->stack = stack_new(sizeof(struct _tree_node*));
|
||
if (self->stack == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
self->queue = queue_new(sizeof(struct _tree_node*));
|
||
if (self->queue == NULL)
|
||
{
|
||
stack_free(&self->stack);
|
||
return false;
|
||
}
|
||
|
||
self->_rebalance = tree_avl_rebalance;
|
||
self->_destory = tree_destory;
|
||
|
||
// -------------------- public --------------------
|
||
// kernel
|
||
self->insert = tree_avl_insert;
|
||
self->delete = tree_avl_delete;
|
||
self->height = tree_height;
|
||
|
||
// base
|
||
self->clear = tree_clear;
|
||
self->empty = tree_empty;
|
||
self->size = tree_size;
|
||
|
||
// iter
|
||
self->iter = tree_iter;
|
||
|
||
// others
|
||
self->max = tree_max;
|
||
self->min = tree_min;
|
||
|
||
// -------------------- default --------------------
|
||
self->compare = default_compare;
|
||
self->print_obj = default_print_obj;
|
||
|
||
return true;
|
||
}
|
||
|
||
static bool tree_rb_init(struct _tree* self, uint32_t obj_size)
|
||
{
|
||
assert(self != NULL);
|
||
|
||
// -------------------- private --------------------
|
||
self->_obj_size = obj_size;
|
||
self->_size = 0;
|
||
// self->_capacity = 64;
|
||
// self->_ratio = 2;
|
||
|
||
self->_root = NULL;
|
||
|
||
self->stack = stack_new(sizeof(struct _tree_node*));
|
||
if (self->stack == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
self->queue = queue_new(sizeof(struct _tree_node*));
|
||
if (self->queue == NULL)
|
||
{
|
||
stack_free(&self->stack);
|
||
return false;
|
||
}
|
||
|
||
self->_rebalance = tree_rb_rebalance;
|
||
self->_destory = tree_destory;
|
||
|
||
// -------------------- public --------------------
|
||
// kernel
|
||
self->insert = tree_rb_insert;
|
||
self->delete = tree_rb_delete;
|
||
self->height = tree_height;
|
||
|
||
// base
|
||
self->clear = tree_clear;
|
||
self->empty = tree_empty;
|
||
self->size = tree_size;
|
||
|
||
// iter
|
||
self->iter = tree_iter;
|
||
|
||
// others
|
||
self->max = tree_max;
|
||
self->min = tree_min;
|
||
|
||
// -------------------- default --------------------
|
||
self->compare = default_compare;
|
||
self->print_obj = default_print_obj;
|
||
|
||
return true;
|
||
}
|
||
|
||
tree_t tree_avl_new(uint32_t obj_size)
|
||
{
|
||
tree_t tree = NULL;
|
||
tree = (struct _tree*)malloc(sizeof(struct _tree));
|
||
if(tree == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
if(tree_avl_init(tree, obj_size) != true)
|
||
{
|
||
free(tree);
|
||
return NULL;
|
||
}
|
||
return tree;
|
||
}
|
||
|
||
tree_t tree_rb_new(uint32_t obj_size)
|
||
{
|
||
tree_t tree = NULL;
|
||
tree = (struct _tree*)malloc(sizeof(struct _tree));
|
||
if(tree == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
if(tree_rb_init(tree, obj_size) != true)
|
||
{
|
||
free(tree);
|
||
return NULL;
|
||
}
|
||
return tree;
|
||
}
|
||
|
||
void tree_free(tree_t* tree)
|
||
{
|
||
if (*tree != NULL)
|
||
{
|
||
(*tree)->_destory(*tree);
|
||
free(*tree);
|
||
}
|
||
*tree = NULL;
|
||
}
|