mirror of
https://gitee.com/apaki/unicstl.git
synced 2025-05-18 11:51:36 +08:00
1395 lines
23 KiB
C
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
|
|
|