unicstl/datastruct/tree.c
2024-06-18 10:08:40 +08:00

1395 lines
23 KiB
C

#include "tree.h"
#if RAVLTREE == 1
// function declare
static bool tree_rebalance(ptree_node_t tree);
bool tree_init(ptree_node_t *tree)
{
*tree = (ptree_node_t)malloc(sizeof(tree_node_t));
if(*tree == NULL)
{
return false;
}
// (*tree)->data = (tree_data_t)0; // the data of header is invalid
(*tree)->left = *tree; // The left subtree of the header node of the tree points to itself
(*tree)->right = NULL; // The right subtree of the header node of the tree points to the root
(*tree)->parent = NULL; // Invalid, because this is the pointer of tree header
(*tree)->balance = 0; // balance of avl tree
return true;
}
void tree_destroy(ptree_node_t *tree)
{
if(*tree != NULL)
{
tree_clear(*tree);
free(*tree);
*tree = NULL;
}
}
bool tree_empty(ptree_node_t tree)
{
return ((tree == NULL) || (tree->left == tree) && (tree->right == NULL)) ? true : false;
}
void tree_clear(ptree_node_t tree)
{
// the header of tree pointer
if(tree != NULL && tree->left == tree)
{
tree_clear(tree->right);
free(tree->right);
tree->right = NULL;
return;
}
if(!tree_empty(tree))
{
if(tree->left != NULL)
{
tree_clear(tree->left);
free(tree->left);
tree->left = NULL;
}
if(tree->right != NULL)
{
tree_clear(tree->right);
free(tree->right);
tree->right = NULL;
}
}
}
static ptree_node_t tree_find(ptree_node_t tree, tree_data_t data)
{
if (tree != NULL && tree->left == tree)
{
return tree_find(tree->right,data);
}
if(tree == NULL)
{
return NULL;
}
if(tree->data == data)
{
return tree;
}
if(data < tree->data)
{
if(tree->left != NULL)
{
return tree_find(tree->left,data);
}
else
{
return tree;
}
}
if(data > tree->data)
{
if(tree->right != NULL)
{
return tree_find(tree->right,data);
}
else
{
return tree;
}
}
// invalid
return NULL;
}
bool tree_insert(ptree_node_t tree, tree_data_t data)
{
ptree_node_t tree_node;
if (tree == NULL)
{
return false;
}
// the header of tree pointer
if(tree != NULL && tree->left == tree)
{
if (tree->right == NULL)
{
ptree_node_t new_item = (ptree_node_t)malloc(sizeof(tree_node_t));
if (new_item == NULL)
{
return false;
}
new_item->data = data;
new_item->left = NULL;
new_item->right = NULL;
// new_item->parent = NULL; // root no parent
new_item->parent = tree; // the parent of root is header of tree
new_item->balance = 0; // balance of avl tree
tree->right = new_item;
return true;
}
else
{
return tree_insert(tree->right, data);
}
}
tree_node = tree_find(tree,data);
if(data < tree_node->data)
{
ptree_node_t new_item = (ptree_node_t)malloc(sizeof(tree_node_t));
if(new_item == NULL)
{
return false;
}
new_item->data = data;
new_item->left = NULL;
new_item->right = NULL;
new_item->parent = tree_node;
new_item->balance = 0; // balance of avl tree
tree_node->left = new_item;
// avl tree rebalance
tree_rebalance(tree_node);
}
else
{
ptree_node_t new_item = (ptree_node_t)malloc(sizeof(tree_node_t));
if(new_item == NULL)
{
return false;
}
new_item->data = data;
new_item->left = NULL;
new_item->right = NULL;
new_item->parent = tree_node;
new_item->balance = 0; // balance of avl tree
tree_node->right = new_item;
// avl tree rebalance
tree_rebalance(tree_node);
}
return true;
}
static ptree_node_t tree_get_node_min(ptree_node_t tree)
{
if (tree != NULL && tree->left == tree)
{
return tree_get_node_min(tree->right);
}
if(tree != NULL)
{
if(tree->left != NULL)
{
return tree_get_node_min(tree->left);
}
else
{
return tree;
}
}
else
{
return NULL;
}
}
static void tree_delete_single_child(ptree_node_t tree)
{
if (tree != NULL && tree->left == tree)
{
tree_delete_single_child(tree->right);
return ;
}
if(tree != NULL)
{
// becaue the parent of root is header of tree
// if(tree->parent == NULL)
if(tree->parent->parent == NULL)
{
// delete the root of tree
if(tree->left == NULL)
{
tree->parent->right = tree->right;
if(tree->right != NULL)
{
tree->right->parent = tree->parent;
}
}
else
{
tree->parent->right = tree->left;
tree->left->parent = tree->parent;
}
}
else
{
// delete other node of tree
if(tree->parent->left == tree)
{
// left subtree
if(tree->left == NULL)
{
tree->parent->left = tree->right;
if(tree->right != NULL)
{
tree->right->parent = tree->parent;
}
}
else
{
tree->parent->left = tree->left;
tree->left->parent = tree->parent;
}
}
else
{
// rigth subtree
if(tree->left == NULL)
{
tree->parent->right = tree->right;
if(tree->right != NULL)
{
tree->right->parent = tree->parent;
}
}
else
{
tree->parent->right = tree->left;
tree->left->parent = tree->parent;
}
}
// avl tree rebalance
tree_rebalance(tree->parent);
}
free(tree);
}
}
static void tree_delete_double_child(ptree_node_t tree)
{
// I think this idea is great!
ptree_node_t t = tree_get_node_min(tree->right);
if(t != NULL)
{
tree->data = t->data;
tree_delete_single_child(t);
}
}
bool tree_delete(ptree_node_t tree, tree_data_t data)
{
ptree_node_t tree_node;
if (tree == NULL)
{
return false;
}
if (tree != NULL && tree->left == tree)
{
return tree_delete(tree->right, data);
}
tree_node = tree_find(tree,data);
if(tree_node->data == data)
{
if((tree_node->left != NULL) && (tree_node->right != NULL))
{
tree_delete_double_child(tree_node);
}
else
{
tree_delete_single_child(tree_node);
}
return true;
}
else
{
return false;
}
}
bool tree_get_min(ptree_node_t tree, tree_data_t *data)
{
if (tree != NULL && tree->left == tree)
{
return tree_get_min(tree->right, data);
}
if(tree != NULL)
{
if(tree->left != NULL)
{
return tree_get_min(tree->left, data);
}
else
{
*data = tree->data;
return true;
}
}
else
{
return false;
}
// invalid but compile prevention warning
return true;
}
bool tree_get_max(ptree_node_t tree, tree_data_t *data)
{
if (tree != NULL && tree->left == tree)
{
return tree_get_max(tree->right, data);
}
if(tree != NULL)
{
if(tree->right != NULL)
{
return tree_get_max(tree->right, data);
}
else
{
*data = tree->data;
return true;
}
}
else
{
return false;
}
// invalid but compile prevention warning
return true;
}
void tree_traversal_depth_preorder(ptree_node_t tree, tree_data_disp_t tree_data_disp)
{
if (tree != NULL && tree->left == tree)
{
tree_traversal_depth_preorder(tree->right, tree_data_disp);
return;
}
if (tree != NULL)
{
tree_data_disp(tree->data);
tree_traversal_depth_preorder(tree->left, tree_data_disp);
tree_traversal_depth_preorder(tree->right, tree_data_disp);
}
}
void tree_traversal_depth_inorder(ptree_node_t tree, tree_data_disp_t tree_data_disp)
{
if (tree != NULL && tree->left == tree)
{
tree_traversal_depth_inorder(tree->right, tree_data_disp);
return;
}
if (tree != NULL)
{
tree_traversal_depth_inorder(tree->left, tree_data_disp);
tree_data_disp(tree->data);
tree_traversal_depth_inorder(tree->right, tree_data_disp);
}
}
void tree_traversal_depth_postorder(ptree_node_t tree, tree_data_disp_t tree_data_disp)
{
}
void tree_traversal_breadth(ptree_node_t tree, tree_data_disp_t tree_data_disp)
{
}
// --------------- AVL ----------------------
static int32_t tree_get_height(ptree_node_t tree)
{
int32_t left_height;
int32_t right_height;
if (tree != NULL && tree->left == tree)
{
return tree_get_height(tree->right);
}
if(tree == NULL)
{
return 0;
}
left_height = tree_get_height(tree->left);
right_height = tree_get_height(tree->right);
return (left_height > right_height) ? (left_height + 1) : (right_height + 1);
}
static void tree_set_balance(ptree_node_t tree)
{
if (tree != NULL && tree->left == tree)
{
tree_get_height(tree->right);
return;
}
if(tree != NULL)
{
tree->balance = tree_get_height(tree->right) - tree_get_height(tree->left);
}
}
static ptree_node_t tree_turn_left(ptree_node_t tree)
{
ptree_node_t tree_node;
if (tree != NULL && tree->left == tree)
{
return tree_turn_left(tree->right);
}
if(tree == NULL)
{
return NULL;
}
// tree -> original node[a]
// tree_node -> original right subnode[b] of [a]
tree_node = tree->right;
// 1. replace the children of the parent node
if(tree->parent->parent != NULL)
{
// not root
if(tree->parent->left == tree)
{
tree->parent->left = tree_node;
}
else
{
tree->parent->right = tree_node;
}
}
tree_node->parent = tree->parent;
// 2. turn left
tree->parent = tree_node;
tree->right = tree_node->left;
tree_node->left = tree;
if(tree->right != NULL)
{
tree->right->parent = tree;
}
tree_set_balance(tree);
tree_set_balance(tree_node);
return tree_node;
}
static ptree_node_t tree_turn_right(ptree_node_t tree)
{
ptree_node_t tree_node;
if (tree != NULL && tree->left == tree)
{
return tree_turn_left(tree->right);
}
if(tree == NULL)
{
return NULL;
}
// tree -> original node[a]
// tree_node -> original left subnode[b] of [a]
tree_node = tree->left;
// 1. replace the children of the parent node
if(tree->parent->parent != NULL)
{
// not root
if(tree->parent->left == tree)
{
tree->parent->left = tree_node;
}
else
{
tree->parent->right = tree_node;
}
}
tree_node->parent = tree->parent;
// 2. turn left
tree->parent = tree_node;
tree->left = tree_node->right;
tree_node->right = tree;
if(tree->left != NULL)
{
tree->left->parent = tree;
}
tree_set_balance(tree);
tree_set_balance(tree_node);
return tree_node;
}
static ptree_node_t tree_turn_left_then_right(ptree_node_t tree)
{
if (tree != NULL && tree->left == tree)
{
return tree_turn_left(tree->right);
}
if(tree == NULL)
{
return NULL;
}
// first left then right
tree->left = tree_turn_left(tree->left);
return tree_turn_right(tree);
}
static ptree_node_t tree_turn_right_then_left(ptree_node_t tree)
{
if (tree != NULL && tree->left == tree)
{
return tree_turn_left(tree->right);
}
if(tree == NULL)
{
return NULL;
}
// first left then right
tree->right = tree_turn_right(tree->right);
return tree_turn_left(tree);
}
bool tree_rebalance(ptree_node_t tree)
{
if (tree != NULL && tree->left == tree)
{
return tree_rebalance(tree->right);
}
if(tree == NULL)
{
return false;
}
tree_set_balance(tree);
// left is greater than right
if(tree->balance == -2)
{
if(tree->left->balance <= 0)
{
// node-left-left
tree = tree_turn_right(tree);
}
else
{
// node-left-rigt
tree = tree_turn_left_then_right(tree);
}
}
// right is greater than left
else if(tree->balance == 2)
{
if(tree->right->balance >= 0)
{
// node-right-right
tree = tree_turn_left(tree);
}
else
{
// node-right-left
tree = tree_turn_right_then_left(tree);
}
}
if(tree->parent->parent != NULL)
{
tree_rebalance(tree->parent);
}
else
{
tree->parent->right = tree;
}
return true;
}
#endif
#if AVLTREE == 1
#include "stack.h"
#include "queue.h"
// function declare
static bool tree_rebalance(ptree_t head, ptree_node_t tree);
bool tree_init(ptree_t *head)
{
*head = (ptree_t)malloc(sizeof(tree_t));
if(*head == NULL)
{
return false;
}
(*head)->tree = NULL;
(*head)->size = 0;
return true;
}
void tree_destroy(ptree_t * head)
{
if(*head != NULL)
{
tree_clear(*head);
free(*head);
*head = NULL;
}
}
bool tree_empty(ptree_t head)
{
return ((head == NULL) || (head->tree == NULL)) ? true : false;
}
void tree_clear(ptree_t head)
{
pqueue_t queue;
ptree_node_t root;
ptree_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 tree_get_size(ptree_t head)
{
return head->size;
}
static ptree_node_t tree_find(ptree_t head, tree_data_t data)
{
ptree_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;
}
bool tree_insert(ptree_t head, tree_data_t data)
{
ptree_node_t tree_node;
ptree_node_t new_node;
if(head == NULL)
{
return false;
}
// no root of tree
if(head->tree == NULL)
{
new_node = (ptree_node_t)malloc(sizeof(tree_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
new_node->balance = 0; // balance of avl tree
head->tree = new_node;
}
else
{
tree_node = tree_find(head,data);
if(data < tree_node->data)
{
new_node = (ptree_node_t)malloc(sizeof(tree_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;
new_node->balance = 0; // balance of avl tree
tree_node->left = new_node;
// avl tree rebalance
tree_rebalance(head, tree_node);
}
else
{
new_node = (ptree_node_t)malloc(sizeof(tree_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;
new_node->balance = 0; // balance of avl tree
tree_node->right = new_node;
// avl tree rebalance
tree_rebalance(head, tree_node);
}
}
if (head->size < _UI32_MAX)
{
head->size++;
}
return true;
}
static ptree_node_t tree_get_node_min(ptree_node_t tree)
{
while(tree != NULL)
{
if(tree->left != NULL)
{
tree = tree->left;
}
else
{
return tree;
}
}
return tree;
}
static void tree_delete_single_child(ptree_t head, ptree_node_t tree)
{
if((head == NULL) || head->tree == NULL)
{
return ;
}
if(tree == NULL)
{
return ;
}
if(tree->parent == NULL)
{
// delete the root of tree
if(tree->left == NULL)
{
head->tree = tree->right;
if(tree->right != NULL)
{
tree->right->parent = tree->parent;
}
}
else
{
head->tree = tree->left;
tree->left->parent = tree->parent;
}
}
else
{
// delete other node of tree
if(tree->parent->left == tree)
{
// left subtree
if(tree->left == NULL)
{
tree->parent->left = tree->right;
if(tree->right != NULL)
{
tree->right->parent = tree->parent;
}
}
else
{
tree->parent->left = tree->left;
tree->left->parent = tree->parent;
}
}
else
{
// rigth subtree
if(tree->left == NULL)
{
tree->parent->right = tree->right;
if(tree->right != NULL)
{
tree->right->parent = tree->parent;
}
}
else
{
tree->parent->right = tree->left;
tree->left->parent = tree->parent;
}
}
// avl tree rebalance
tree_rebalance(head, tree->parent);
}
free(tree);
}
static void tree_delete_double_child(ptree_t head, ptree_node_t tree)
{
if((head == NULL) || head->tree == NULL)
{
return ;
}
// I think this idea is great!
ptree_node_t tree_node = tree_get_node_min(tree->right);
if(tree_node != NULL)
{
tree->data = tree_node->data;
tree_delete_single_child(head, tree_node);
}
}
bool tree_delete(ptree_t head, tree_data_t data)
{
ptree_node_t tree_node;
if((head == NULL) || head->tree == NULL)
{
return false;
}
tree_node = tree_find(head,data);
if(tree_node == NULL)
{
return false;
}
if((tree_node->left != NULL) && (tree_node->right != NULL))
{
tree_delete_double_child(head, tree_node);
}
else
{
tree_delete_single_child(head, tree_node);
}
if(head->size > 0)
{
head->size--;
}
return true;
}
bool tree_get_min(ptree_t head, tree_data_t *data)
{
ptree_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 tree_get_max(ptree_t head, tree_data_t *data)
{
ptree_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;
}
void tree_traversal_depth_preorder(ptree_t head, tree_data_disp_t tree_data_disp)
{
pstack_t stack;
ptree_node_t root;
ptree_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 tree_traversal_depth_inorder(ptree_t head, tree_data_disp_t tree_data_disp)
{
pstack_t stack;
ptree_node_t root;
ptree_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 tree_traversal_depth_postorder(ptree_t head, tree_data_disp_t tree_data_disp)
{
pstack_t stack;
pstack_t stack_disp;
ptree_node_t root;
ptree_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);
}
void tree_traversal_breadth(ptree_t head, tree_data_disp_t tree_data_disp)
{
pqueue_t queue;
ptree_node_t root;
ptree_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);
}
// --------------- AVL ----------------------
static int32_t tree_get_height(ptree_node_t tree)
{
pqueue_t queue;
ptree_node_t root;
ptree_node_t tree_node;
int32_t height = 0;
uint32_t count = 0;
uint32_t next_level_node_cnt = 0;
if(tree == NULL)
{
return false;
}
root = 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);
}
if(count == next_level_node_cnt)
{
next_level_node_cnt = queue_get_size(queue);
count = 1;
height ++;
}
else
{
count++;
}
}
}
queue_destroy(&queue);
return height;
}
static void tree_set_balance(ptree_node_t tree)
{
if (tree != NULL)
{
tree->balance = tree_get_height(tree->right) - tree_get_height(tree->left);
}
}
static ptree_node_t tree_turn_left(ptree_node_t tree)
{
ptree_node_t tree_node;
ptree_node_t root;
if(tree == NULL)
{
return NULL;
}
root = tree;
// tree -> original node[a]
// tree_node -> original right subnode[b] of [a]
tree_node = root->right;
// 1. replace the children of the parent node
if(root->parent != NULL)
{
// not root
if(root->parent->left == root)
{
root->parent->left = tree_node;
}
else
{
root->parent->right = tree_node;
}
}
tree_node->parent = root->parent;
// 2. turn left
root->parent = tree_node;
root->right = tree_node->left;
tree_node->left = root;
if(root->right != NULL)
{
root->right->parent = root;
}
// 3. set balance
tree_set_balance(root);
tree_set_balance(tree_node);
return tree_node;
}
static ptree_node_t tree_turn_right(ptree_node_t tree)
{
ptree_node_t tree_node;
ptree_node_t root;
if(tree == NULL)
{
return NULL;
}
root = tree;
// tree -> original node[a]
// tree_node -> original left subnode[b] of [a]
tree_node = root->left;
// 1. replace the children of the parent node
if(root->parent != NULL)
{
// not root
if(root->parent->left == root)
{
root->parent->left = tree_node;
}
else
{
root->parent->right = tree_node;
}
}
tree_node->parent = root->parent;
// 2. turn left
root->parent = tree_node;
root->left = tree_node->right;
tree_node->right = root;
if(root->left != NULL)
{
root->left->parent = root;
}
tree_set_balance(root);
tree_set_balance(tree_node);
return tree_node;
}
static ptree_node_t tree_turn_left_then_right(ptree_node_t tree)
{
ptree_node_t root;
if(tree == NULL)
{
return NULL;
}
root = tree;
// first left then right
root->left = tree_turn_left(root->left);
return tree_turn_right(root);
}
static ptree_node_t tree_turn_right_then_left(ptree_node_t tree)
{
ptree_node_t root;
if(tree == NULL)
{
return NULL;
}
root = tree;
// first left then right
root->right = tree_turn_right(root->right);
return tree_turn_left(root);
}
static bool tree_rebalance(ptree_t head, ptree_node_t tree)
{
ptree_node_t root;
if((head == NULL) || head->tree == NULL)
{
return false;
}
if(tree == NULL)
{
return false;
}
do
{
tree_set_balance(tree);
// left is greater than right
if(tree->balance == -2)
{
if(tree->left->balance <= 0)
{
// node-left-left
tree = tree_turn_right(tree);
}
else
{
// node-left-rigt
tree = tree_turn_left_then_right(tree);
}
}
// right is greater than left
else if(tree->balance == 2)
{
if(tree->right->balance >= 0)
{
// node-right-right
tree = tree_turn_left(tree);
}
else
{
// node-right-left
tree = tree_turn_right_then_left(tree);
}
}
root = tree;
tree = tree->parent;
}while(tree != NULL);
head->tree = root;
return true;
}
#endif