mirror of
https://gitee.com/apaki/unicstl.git
synced 2025-05-18 03:51:35 +08:00
1969 lines
41 KiB
C
1969 lines
41 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"
|
||
|
||
#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
|
||
|
||
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);
|
||
assert(root->right != NULL);
|
||
struct _tree_node* node = root->right;
|
||
|
||
if(root->parent != NULL)
|
||
{
|
||
if(root->parent->left == root) // step1
|
||
{
|
||
root->parent->left = node;
|
||
}
|
||
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
|
||
node->left = root; // step5
|
||
|
||
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);
|
||
assert(root->left != NULL);
|
||
struct _tree_node* node = root->left;
|
||
|
||
if(root->parent != NULL)
|
||
{
|
||
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
|
||
node->right = root; // step5
|
||
|
||
tree_set_balance(self, root);
|
||
tree_set_balance(self, node);
|
||
return node;
|
||
}
|
||
|
||
static struct _tree_node* tree_trun_left_then_right(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
assert(root != NULL);
|
||
assert(root->left != NULL);
|
||
struct _tree_node* node = root->left;
|
||
|
||
tree_turn_left(self, root->left);
|
||
node = tree_turn_right(self, root);
|
||
return node;
|
||
}
|
||
|
||
static struct _tree_node* tree_trun_right_then_left(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
assert(root != NULL);
|
||
assert(root->right != NULL);
|
||
struct _tree_node* node = root->right;
|
||
tree_turn_right(self, root->right);
|
||
node = tree_turn_left(self, root);
|
||
return node;
|
||
}
|
||
|
||
uint32_t tree_height(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
if(root == NULL)
|
||
{
|
||
return 0;
|
||
}
|
||
uint32_t left_height = tree_height(self, root->left);
|
||
uint32_t right_height = tree_height(self, root->right);
|
||
return (left_height > right_height) ? (left_height + 1) : (right_height + 1);
|
||
}
|
||
|
||
/**
|
||
* @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 | > 1 | > 0 | <20><><EFBFBD><EFBFBD>
|
||
* | 2 | > 1 | < 0 | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
* | 3 | < -1 | < 0 | <20><><EFBFBD><EFBFBD>
|
||
* | 4 | < -1 | > 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)
|
||
{
|
||
assert(self != NULL);
|
||
if(root == NULL)
|
||
{
|
||
return true;
|
||
}
|
||
|
||
tree_set_balance(self, root);
|
||
int balance = root->balance;
|
||
if(balance > 1)
|
||
{
|
||
if(root->right->balance > 0)
|
||
{
|
||
root = tree_turn_left(self, root);
|
||
}
|
||
else if(root->right->balance < 0)
|
||
{
|
||
root = tree_trun_left_then_right(self, root);
|
||
}
|
||
}
|
||
else if(balance < 1)
|
||
{
|
||
if(root->left->balance < 0)
|
||
{
|
||
root = tree_turn_right(self, root);
|
||
}
|
||
else if(root->left->balance > 0)
|
||
{
|
||
root = tree_trun_right_then_left(self, root);
|
||
}
|
||
}
|
||
|
||
if(root->parent != NULL)
|
||
{
|
||
tree_avl_rebalance(self, root->parent);
|
||
}
|
||
else
|
||
{
|
||
self->_root = root;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
bool tree_avl_delete(struct _tree* self, void* obj)
|
||
{
|
||
assert(self != NULL);
|
||
assert(obj != NULL);
|
||
assert(self->compare != NULL);
|
||
|
||
// if
|
||
if(self->empty(self))
|
||
{
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
struct _tree_node* node = self->find(self, obj);
|
||
if(node == NULL)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
if(obj != NULL)
|
||
{
|
||
memmove(obj, node->obj, self->_obj_size);
|
||
}
|
||
|
||
if(node->parent->left == node)
|
||
{
|
||
node->parent->left = NULL;
|
||
}
|
||
else if(node->parent->right == node)
|
||
{
|
||
|
||
}
|
||
tree_node_free(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);
|
||
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)
|
||
{
|
||
assert(self != NULL);
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
|
||
void tree_avl_inorder(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
|
||
void tree_avl_postorder(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
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);
|
||
}
|
||
}
|
||
|
||
// traversal breadth
|
||
void tree_avl_breadth(struct _tree* self, struct _tree_node* root)
|
||
{
|
||
assert(self != NULL);
|
||
struct _tree_node* node = self->_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);
|
||
}
|
||
|
||
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->_root = NULL;
|
||
|
||
return true;
|
||
}
|
||
|
||
bool tree_rb_init(struct _tree *self, uint32_t obj_size)
|
||
{
|
||
|
||
}
|
||
|
||
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);
|
||
}
|
||
}
|