mirror of
https://gitee.com/apaki/unicstl.git
synced 2025-05-18 03:51:35 +08:00
1217 lines
27 KiB
C
1217 lines
27 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"
|
||
|
||
static void tree_set_balance(struct _tree* self, struct _tree_node * node)
|
||
{
|
||
assert(self != NULL);
|
||
if(node == NULL)
|
||
{
|
||
return;
|
||
}
|
||
node->balance = self->height(self, node->right) - self->height(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;
|
||
}
|
||
|
||
int32_t tree_height(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
#if 0
|
||
assert(self != NULL);
|
||
if(root == NULL)
|
||
{
|
||
return 0;
|
||
}
|
||
int32_t left_height = tree_height(self, root->left);
|
||
int32_t right_height = tree_height(self, root->right);
|
||
return (left_height > right_height) ? (left_height + 1) : (right_height + 1);
|
||
#else
|
||
assert(self != NULL);
|
||
if(root == NULL)
|
||
{
|
||
return 0;
|
||
}
|
||
int32_t height = 0;
|
||
int32_t count_cur_level = 0;
|
||
int32_t count_next_level = 0;
|
||
|
||
struct _tree_node* node = root;
|
||
queue_t queue = queue_new();
|
||
queue_init(queue, 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
|
||
}
|
||
|
||
/**
|
||
* @brief
|
||
*
|
||
* <20><> balance = rigth - left Ϊ<><CEAA><EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
*
|
||
* | <20><><EFBFBD><EFBFBD> | root->balance | node->balance | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ |
|
||
* | ---- | ------------ | -------------- | -------- |
|
||
* | 1 | 2 | >= 0 | <20><><EFBFBD><EFBFBD>
|
||
* | 2 | 2 | < 0 | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
* | 3 | -2 | <= 0 | <20><><EFBFBD><EFBFBD>
|
||
* | 4 | -2 | > 0 | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
*
|
||
* @param self
|
||
* @return true
|
||
* @return false
|
||
*/
|
||
static bool tree_avl_rebalance(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
#if 0
|
||
assert(self != NULL);
|
||
if(root == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
if(root->left == NULL && root->right == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// self->print_obj(root->obj);
|
||
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_node_new(struct _tree* self, void* obj)
|
||
{
|
||
assert(self != NULL);
|
||
|
||
void * obj_new = malloc(self->_obj_size);
|
||
if (obj_new == NULL)
|
||
{
|
||
goto done;
|
||
}
|
||
memmove(obj_new, obj, self->_obj_size);
|
||
|
||
struct _tree_node* node_new = (struct _tree_node*)malloc(sizeof(struct _tree_node));
|
||
if(node_new == NULL)
|
||
{
|
||
goto done;
|
||
}
|
||
node_new->obj = obj_new;
|
||
node_new->parent = NULL;
|
||
node_new->left = NULL;
|
||
node_new->right = NULL;
|
||
node_new->balance = 0;
|
||
|
||
return node_new;
|
||
done:
|
||
if(obj_new != NULL)
|
||
{
|
||
free(obj_new);
|
||
}
|
||
if(node_new != NULL)
|
||
{
|
||
free(node_new);
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
static bool tree_node_free(struct _tree_node* node)
|
||
{
|
||
if(node != NULL)
|
||
{
|
||
if(node->obj != NULL)
|
||
{
|
||
free(node->obj);
|
||
}
|
||
free(node);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* @brief <20><><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2>Ҳ<EFBFBD><D2B2><EFBFBD>λ<EFBFBD><CEBB>
|
||
*
|
||
* @param self <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
|
||
* @param obj Ҫ<><D2AA><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD>
|
||
*/
|
||
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)
|
||
{
|
||
break;
|
||
}
|
||
else if(self->compare(obj, root->obj) < 0)
|
||
{
|
||
if(root->left == NULL)
|
||
{
|
||
break;
|
||
}
|
||
root = root->left;
|
||
}
|
||
else
|
||
{
|
||
if(root->right == NULL)
|
||
{
|
||
break;
|
||
}
|
||
root = root->right;
|
||
}
|
||
}
|
||
return root;
|
||
}
|
||
|
||
|
||
bool tree_avl_insert(struct _tree* self, void* obj)
|
||
{
|
||
assert(self != NULL);
|
||
assert(obj != NULL);
|
||
assert(self->compare != NULL);
|
||
|
||
struct _tree_node* node = tree_node_new(self, obj);
|
||
if(node == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// if no root
|
||
if(self->_root == NULL)
|
||
{
|
||
self->_root = node;
|
||
}
|
||
else
|
||
{
|
||
// insert the node
|
||
struct _tree_node* root = tree_find_pos(self, obj);
|
||
if(self->compare(obj, root->obj) < 0)
|
||
{
|
||
root->left = node;
|
||
node->parent = root;
|
||
}
|
||
else if(self->compare(obj, root->obj) > 0)
|
||
{
|
||
root->right = node;
|
||
node->parent = root;
|
||
}
|
||
else
|
||
{
|
||
// if obj exist, just return false
|
||
tree_node_free(node);
|
||
return false;
|
||
}
|
||
|
||
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 = self->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;
|
||
}
|
||
|
||
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 = self->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;
|
||
}
|
||
|
||
struct _tree_node * tree_avl_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;
|
||
}
|
||
|
||
bool tree_clear(struct _tree* self)
|
||
{
|
||
assert(self != NULL);
|
||
if(self->_root == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
struct _tree_node* node = self->_root;
|
||
queue_t queue = queue_new();
|
||
queue_init(queue, 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;
|
||
}
|
||
|
||
bool tree_empty(struct _tree* self)
|
||
{
|
||
assert(self != NULL);
|
||
return !self->size(self);
|
||
}
|
||
|
||
uint32_t tree_size(struct _tree* self)
|
||
{
|
||
assert(self != NULL);
|
||
return self->_size;
|
||
}
|
||
|
||
// free
|
||
void tree_destory(struct _tree* self)
|
||
{
|
||
assert(self != NULL);
|
||
self->clear(self);
|
||
self->_root = NULL;
|
||
}
|
||
|
||
void tree_order(struct _tree* self, bool right_priority)
|
||
{
|
||
assert(self != NULL);
|
||
self->_right_priority = right_priority;
|
||
}
|
||
|
||
void tree_avl_preorder(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
#if 0
|
||
assert(self != NULL);
|
||
if(root == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if(!self->_right_priority)
|
||
{
|
||
self->print_obj(root->obj);
|
||
if(root->left != NULL)
|
||
{
|
||
tree_avl_preorder(self, root->left);
|
||
}
|
||
if(root->right != NULL)
|
||
{
|
||
tree_avl_preorder(self, root->right);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
self->print_obj(root->obj);
|
||
if(root->right != NULL)
|
||
{
|
||
tree_avl_preorder(self, root->right);
|
||
}
|
||
if(root->left != NULL)
|
||
{
|
||
tree_avl_preorder(self, root->left);
|
||
}
|
||
}
|
||
#else
|
||
assert(self != NULL);
|
||
if(root == NULL)
|
||
{
|
||
return;
|
||
}
|
||
struct _tree_node* node = root;
|
||
|
||
stack_t stack = stack_new();
|
||
stack_init(stack, sizeof(struct _tree_node*));
|
||
|
||
if(!self->_right_priority) // left priority
|
||
{
|
||
while(!stack->empty(stack) || node != NULL)
|
||
{
|
||
if(node != NULL)
|
||
{
|
||
self->print_obj(node->obj);
|
||
|
||
stack->push(stack, &node);
|
||
node = node->left;
|
||
}
|
||
else
|
||
{
|
||
stack->pop(stack, &node);
|
||
node = node->right;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
while(!stack->empty(stack) || node != NULL)
|
||
{
|
||
if(node != NULL)
|
||
{
|
||
self->print_obj(node->obj);
|
||
|
||
stack->push(stack, &node);
|
||
node = node->right;
|
||
}
|
||
else
|
||
{
|
||
stack->pop(stack, &node);
|
||
node = node->left;
|
||
}
|
||
}
|
||
}
|
||
stack_free(stack);
|
||
#endif
|
||
}
|
||
|
||
void tree_avl_inorder(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
#if 0
|
||
assert(self != NULL);
|
||
if(root == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if(!self->_right_priority)
|
||
{
|
||
if(root->left != NULL)
|
||
{
|
||
tree_avl_inorder(self, root->left);
|
||
}
|
||
self->print_obj(root->obj);
|
||
if(root->right != NULL)
|
||
{
|
||
tree_avl_inorder(self, root->right);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if(root->right != NULL)
|
||
{
|
||
tree_avl_inorder(self, root->right);
|
||
}
|
||
self->print_obj(root->obj);
|
||
if(root->left != NULL)
|
||
{
|
||
tree_avl_inorder(self, root->left);
|
||
}
|
||
}
|
||
#else
|
||
assert(self != NULL);
|
||
if(root == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
struct _tree_node *node = root;
|
||
|
||
stack_t stack = stack_new();
|
||
stack_init(stack, sizeof(struct _tree_node*));
|
||
|
||
if(!self->_right_priority) // left priority
|
||
{
|
||
while(!stack->empty(stack) || node != NULL)
|
||
{
|
||
if(node != NULL)
|
||
{
|
||
stack->push(stack, &node);
|
||
node = node->left;
|
||
}
|
||
else
|
||
{
|
||
stack->pop(stack, &node);
|
||
self->print_obj(node->obj);
|
||
|
||
node = node->right;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
while(node != NULL || !stack->empty(stack))
|
||
{
|
||
if(node != NULL)
|
||
{
|
||
stack->push(stack, &node);
|
||
node = node->right;
|
||
}
|
||
else
|
||
{
|
||
stack->pop(stack, &node);
|
||
self->print_obj(node->obj);
|
||
|
||
node = node->left;
|
||
}
|
||
}
|
||
}
|
||
stack_free(stack);
|
||
#endif
|
||
}
|
||
|
||
void tree_avl_postorder(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
#if 0
|
||
assert(self != NULL);
|
||
if(root == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if(!self->_right_priority)
|
||
{
|
||
if(root->left != NULL)
|
||
{
|
||
tree_avl_postorder(self, root->left);
|
||
}
|
||
if(root->right != NULL)
|
||
{
|
||
tree_avl_postorder(self, root->right);
|
||
}
|
||
self->print_obj(root->obj);
|
||
}
|
||
else
|
||
{
|
||
if(root->right != NULL)
|
||
{
|
||
tree_avl_postorder(self, root->right);
|
||
}
|
||
if(root->left != NULL)
|
||
{
|
||
tree_avl_postorder(self, root->left);
|
||
}
|
||
self->print_obj(root->obj);
|
||
}
|
||
#else
|
||
assert(self != NULL);
|
||
if(root == NULL)
|
||
{
|
||
return;
|
||
}
|
||
struct _tree_node* node = root;
|
||
|
||
stack_t stack2 = stack_new();
|
||
stack_init(stack2, sizeof(struct _tree_node*));
|
||
|
||
// because: left:postorder == right:the reverse of preorder
|
||
stack_t stack = stack_new();
|
||
stack_init(stack, sizeof(struct _tree_node*));
|
||
|
||
if(!self->_right_priority) // left priority
|
||
{
|
||
while(!stack->empty(stack) || node != NULL)
|
||
{
|
||
if(node != NULL)
|
||
{
|
||
stack2->push(stack2, &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)
|
||
{
|
||
stack2->push(stack2, &node);
|
||
|
||
stack->push(stack, &node);
|
||
node = node->left;
|
||
}
|
||
else
|
||
{
|
||
stack->pop(stack, &node);
|
||
node = node->right;
|
||
}
|
||
}
|
||
}
|
||
|
||
while(!stack2->empty(stack2))
|
||
{
|
||
stack2->pop(stack2, &node);
|
||
self->print_obj(node->obj);
|
||
}
|
||
|
||
stack_free(stack);
|
||
stack_free(stack2);
|
||
#endif
|
||
}
|
||
|
||
// traversal breadth
|
||
void tree_avl_breadth(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
if(root == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
struct _tree_node* node = root;
|
||
queue_t queue = queue_new();
|
||
queue_init(queue, sizeof(struct _tree_node*));
|
||
|
||
if(node != NULL)
|
||
{
|
||
queue->push(queue, &node);
|
||
while(!queue->empty(queue))
|
||
{
|
||
queue->pop(queue, &node);
|
||
if(!self->_right_priority)
|
||
{
|
||
if(node->left != NULL)
|
||
{
|
||
queue->push(queue, &node->left);
|
||
}
|
||
if(node->right != NULL)
|
||
{
|
||
queue->push(queue, &node->right);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if(node->right != NULL)
|
||
{
|
||
queue->push(queue, &node->right);
|
||
}
|
||
if(node->left != NULL)
|
||
{
|
||
queue->push(queue, &node->left);
|
||
}
|
||
}
|
||
self->print_obj(node->obj);
|
||
}
|
||
}
|
||
queue_free(queue);
|
||
}
|
||
|
||
static struct _tree_node* tree_find_min(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
#if 0
|
||
if(root == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
if(root->left == NULL)
|
||
{
|
||
return root;
|
||
}
|
||
return tree_find_min(self, root->left);
|
||
#else
|
||
while(root != NULL)
|
||
{
|
||
if(root->left != NULL)
|
||
{
|
||
root = root->left;
|
||
}
|
||
else
|
||
{
|
||
return root;
|
||
}
|
||
}
|
||
return root;
|
||
#endif
|
||
}
|
||
|
||
static struct _tree_node* tree_find_max(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
#if 0
|
||
assert(self != NULL);
|
||
if(root == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
if(root->right == NULL)
|
||
{
|
||
return root;
|
||
}
|
||
return tree_find_max(self, root->right);
|
||
#else
|
||
while(root != NULL)
|
||
{
|
||
if(root->right != NULL)
|
||
{
|
||
root = root->right;
|
||
}
|
||
else
|
||
{
|
||
return root;
|
||
}
|
||
}
|
||
return root;
|
||
#endif
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
bool tree_avl_init(struct _tree *self, uint32_t obj_size)
|
||
{
|
||
assert(self != NULL);
|
||
|
||
self->_obj_size = obj_size;
|
||
self->_size = 0;
|
||
// self->_capacity = 64;
|
||
// self->_ratio = 2;
|
||
|
||
self->_right_priority = false;
|
||
|
||
self->insert = tree_avl_insert;
|
||
self->delete = tree_avl_delete;
|
||
self->clear = tree_clear;
|
||
self->empty = tree_empty;
|
||
self->size = tree_size;
|
||
self->destory = tree_destory;
|
||
self->preorder = tree_avl_preorder;
|
||
self->inorder = tree_avl_inorder;
|
||
self->postorder = tree_avl_postorder;
|
||
self->breadth = tree_avl_breadth;
|
||
self->order = tree_order;
|
||
self->find = tree_avl_find;
|
||
self->height = tree_height;
|
||
self->rebalance = tree_avl_rebalance;
|
||
self->find_max = tree_find_max;
|
||
self->find_min = tree_find_min;
|
||
self->max = tree_max;
|
||
self->min = tree_min;
|
||
|
||
self->_root = NULL;
|
||
|
||
return true;
|
||
}
|
||
|
||
rbt_color tree_color(struct _tree_node* node)
|
||
{
|
||
assert(node != NULL);
|
||
return node->color;
|
||
}
|
||
|
||
bool tree_set_color(struct _tree_node* node, rbt_color color)
|
||
{
|
||
assert(node != NULL);
|
||
node->color = color;
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* @brief
|
||
*
|
||
* <20><> balance = rigth - left Ϊ<><CEAA><EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
*
|
||
* | <20><><EFBFBD><EFBFBD> | root->balance | node->balance | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ |
|
||
* | ---- | ------------ | -------------- | -------- |
|
||
* | 1 | 2 | >= 0 | <20><><EFBFBD><EFBFBD>
|
||
* | 2 | 2 | < 0 | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
* | 3 | -2 | <= 0 | <20><><EFBFBD><EFBFBD>
|
||
* | 4 | -2 | > 0 | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
*
|
||
* @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 <20>²<EFBFBD><C2B2><EFBFBD><EFBFBD>ڵ<EFBFBD>Ϊ<EFBFBD><CEAA>ɫ<EFBFBD><C9AB><EFBFBD>Ҹ<EFBFBD><D2B8>ڵ<EFBFBD>Ϊ<EFBFBD><CEAA>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD><C2A3><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
*
|
||
* <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>[1-3]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>[4-6]<5D>ԳƲ<D4B3><C6B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
*
|
||
* ԭ<><D4AD>ֻ<EFBFBD><D6BB>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>취ά<ECB7A8>ֺ<EFBFBD><D6BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʲ<EFBFBD><CAB2><EFBFBD>
|
||
*
|
||
* | <20><><EFBFBD><EFBFBD> | ˵<><CBB5> | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ |
|
||
* | ---- | --- | -------- |
|
||
* | 0 | <20><><EFBFBD>ڵ<EFBFBD>Ϊ<EFBFBD><CEAA>ɫ | <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD>
|
||
* | 1 | <20><><EFBFBD>죬ү<ECA3AC>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD>ڣ<EFBFBD>ү<EFBFBD>죬<EFBFBD><ECA3AC><EFBFBD><EFBFBD>
|
||
* | 2 | <20><><EFBFBD>죬ү<ECA3AC>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD>ү<EFBFBD><D2AF><EFBFBD><EFBFBD>ͬһ<CDAC>ߣ<EFBFBD><DFA3><EFBFBD><EFBFBD>ڣ<EFBFBD>ү<EFBFBD>죬ү<ECA3AC><D2AF>/<2F><><EFBFBD><EFBFBD>
|
||
* | 3 | <20><><EFBFBD>죬ү<ECA3AC>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD>ү<EFBFBD><D2AF><EFBFBD>ڲ<EFBFBD>ͬ<EFBFBD>ߣ<EFBFBD><DFA3>ȸ<EFBFBD><C8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¸<EFBFBD><C2B8><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD>ү<EFBFBD>죬ү<ECA3AC><D2AF>/<2F><><EFBFBD><EFBFBD>
|
||
*/
|
||
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_turn_left(self, father);
|
||
node->color = RBT_BLACK;
|
||
}
|
||
else
|
||
{
|
||
father->color = RBT_BLACK;
|
||
}
|
||
grandfather->color = RBT_RED;
|
||
tree_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_turn_right(self, father);
|
||
node->color = RBT_BLACK;
|
||
}
|
||
else
|
||
{
|
||
father->color = RBT_BLACK;
|
||
}
|
||
grandfather->color = RBT_RED;
|
||
tree_turn_left(self, grandfather);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if(node->parent == NULL)
|
||
{
|
||
self->_root = node;
|
||
node->color = RBT_BLACK;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool tree_rb_init(struct _tree *self, uint32_t obj_size)
|
||
{
|
||
assert(self != NULL);
|
||
self->_obj_size = obj_size;
|
||
self->_size = 0;
|
||
// self->_capacity = 64;
|
||
// self->_ratio = 2;
|
||
|
||
self->_right_priority = false;
|
||
|
||
self->insert = tree_avl_insert;
|
||
self->delete = tree_avl_delete;
|
||
self->clear = tree_clear;
|
||
self->empty = tree_empty;
|
||
self->size = tree_size;
|
||
self->destory = tree_destory;
|
||
self->preorder = tree_avl_preorder;
|
||
self->inorder = tree_avl_inorder;
|
||
self->postorder = tree_avl_postorder;
|
||
self->breadth = tree_avl_breadth;
|
||
self->order = tree_order;
|
||
self->find = tree_avl_find;
|
||
self->height = tree_height;
|
||
self->rebalance = tree_rb_rebalance;
|
||
self->find_max = tree_find_max;
|
||
self->find_min = tree_find_min;
|
||
self->max = tree_max;
|
||
self->min = tree_min;
|
||
|
||
self->_root = NULL;
|
||
return true;
|
||
}
|
||
|
||
tree_t tree_new(void)
|
||
{
|
||
return (struct _tree*)malloc(sizeof(struct _tree));
|
||
}
|
||
|
||
void tree_free(tree_t tree)
|
||
{
|
||
if(tree != NULL)
|
||
{
|
||
tree->destory(tree);
|
||
free(tree);
|
||
}
|
||
}
|