JCEC-comp/JCEC-fastdfs/fastcommon/avl_tree.c

790 lines
14 KiB
C
Executable File

#include "avl_tree.h"
int avl_tree_init(AVLTreeInfo *tree, FreeDataFunc free_data_func, \
CompareFunc compare_func)
{
tree->root = NULL;
tree->free_data_func = free_data_func;
tree->compare_func = compare_func;
return 0;
}
static void avl_tree_destroy_loop(FreeDataFunc free_data_func, \
AVLTreeNode *pCurrentNode)
{
if (pCurrentNode->left != NULL)
{
avl_tree_destroy_loop(free_data_func, pCurrentNode->left);
}
if (pCurrentNode->right != NULL)
{
avl_tree_destroy_loop(free_data_func, pCurrentNode->right);
}
if (free_data_func != NULL)
{
free_data_func(pCurrentNode->data);
}
free(pCurrentNode);
}
void avl_tree_destroy(AVLTreeInfo *tree)
{
if (tree == NULL)
{
return;
}
if (tree->root != NULL)
{
avl_tree_destroy_loop(tree->free_data_func, tree->root);
tree->root = NULL;
}
}
static AVLTreeNode *createTreeNode(AVLTreeNode *pParentNode, void *target_data)
{
AVLTreeNode *pNewNode;
pNewNode = (AVLTreeNode *)malloc(sizeof(AVLTreeNode));
if (pNewNode == NULL)
{
/*
fprintf(stderr, "file: "__FILE__", line: %d, " \
"malloc %d bytes fail!\n", __LINE__, \
(int)sizeof(AVLTreeNode));
*/
return NULL;
}
pNewNode->left = pNewNode->right = NULL;
pNewNode->data = target_data;
pNewNode->balance = 0;
return pNewNode;
}
static void avlRotateLeft(AVLTreeNode *pRotateNode, AVLTreeNode **ppRaiseNode)
{
*ppRaiseNode = pRotateNode->right;
pRotateNode->right = (*ppRaiseNode)->left;
(*ppRaiseNode)->left = pRotateNode;
}
static void avlRotateRight(AVLTreeNode *pRotateNode, AVLTreeNode **ppRaiseNode)
{
*ppRaiseNode = pRotateNode->left;
pRotateNode->left = (*ppRaiseNode)->right;
(*ppRaiseNode)->right = pRotateNode;
}
static void avlLeftBalanceWhenInsert(AVLTreeNode **pTreeNode, int *taller)
{
AVLTreeNode *leftsub;
AVLTreeNode *rightsub;
leftsub = (*pTreeNode)->left;
switch (leftsub->balance)
{
case -1 :
(*pTreeNode)->balance = leftsub->balance = 0;
avlRotateRight (*pTreeNode, pTreeNode);
*taller = 0;
break;
case 0 :
break;
case 1 :
rightsub = leftsub->right;
switch ( rightsub->balance )
{
case -1:
(*pTreeNode)->balance = 1;
leftsub->balance = 0;
break;
case 0 :
(*pTreeNode)->balance = leftsub->balance = 0;
break;
case 1 :
(*pTreeNode)->balance = 0;
leftsub->balance = -1;
break;
}
rightsub->balance = 0;
avlRotateLeft( leftsub, &((*pTreeNode)->left));
avlRotateRight(*pTreeNode, pTreeNode);
*taller = 0;
}
}
static void avlRightBalanceWhenInsert(AVLTreeNode **pTreeNode, int *taller)
{
AVLTreeNode *rightsub;
AVLTreeNode *leftsub;
rightsub = (*pTreeNode)->right;
switch (rightsub->balance)
{
case 1:
(*pTreeNode)->balance = rightsub->balance = 0;
avlRotateLeft(*pTreeNode, pTreeNode);
*taller = 0;
break;
case 0:
break;
case -1:
leftsub = rightsub->left;
switch (leftsub->balance)
{
case 1 :
(*pTreeNode)->balance = -1;
rightsub->balance = 0;
break;
case 0 :
(*pTreeNode)->balance = rightsub->balance = 0;
break;
case -1 :
(*pTreeNode)->balance = 0;
rightsub->balance = 1;
break;
}
leftsub->balance = 0;
avlRotateRight(rightsub, &((*pTreeNode)->right));
avlRotateLeft(*pTreeNode, pTreeNode);
*taller = 0;
}
}
static int avl_tree_insert_loop(CompareFunc compare_func, AVLTreeNode **pCurrentNode, \
void *target_data, int *taller)
{
int nCompRes;
int success;
if (*pCurrentNode == NULL)
{
*pCurrentNode = createTreeNode(*pCurrentNode, target_data);
if (*pCurrentNode != NULL)
{
*taller = 1;
return 1;
}
else
{
return -ENOMEM;
}
}
nCompRes = compare_func((*pCurrentNode)->data, target_data);
if (nCompRes > 0)
{
success = avl_tree_insert_loop(compare_func, \
&((*pCurrentNode)->left), target_data, taller);
if (*taller != 0)
{
switch ((*pCurrentNode)->balance)
{
case -1:
avlLeftBalanceWhenInsert(pCurrentNode, taller);
break;
case 0:
(*pCurrentNode)->balance = -1;
break;
case 1:
(*pCurrentNode)->balance = 0;
*taller = 0;
break;
}
}
}
else if (nCompRes < 0)
{
success = avl_tree_insert_loop(compare_func, \
&((*pCurrentNode)->right), target_data, taller);
if (*taller != 0)
{
switch ((*pCurrentNode)->balance)
{
case -1:
(*pCurrentNode)->balance = 0;
*taller = 0;
break;
case 0:
(*pCurrentNode)->balance = 1;
break;
case 1:
avlRightBalanceWhenInsert(pCurrentNode, taller);
break;
}
}
}
else
{
return 0;
}
return success;
}
int avl_tree_insert(AVLTreeInfo *tree, void *data)
{
int taller;
taller = 0;
return avl_tree_insert_loop(tree->compare_func, &(tree->root), \
data, &taller);
}
static int avl_tree_replace_loop(CompareFunc compare_func, \
FreeDataFunc free_data_func, AVLTreeNode **pCurrentNode, \
void *target_data, int *taller)
{
int nCompRes;
int success;
if (*pCurrentNode == NULL )
{
*pCurrentNode = createTreeNode(*pCurrentNode, target_data);
if (*pCurrentNode != NULL)
{
*taller = 1;
return 1;
}
else
{
return -ENOMEM;
}
}
nCompRes = compare_func((*pCurrentNode)->data, target_data);
if (nCompRes > 0)
{
success = avl_tree_replace_loop(compare_func, free_data_func,
&((*pCurrentNode)->left), target_data, taller);
if (*taller != 0)
{
switch ((*pCurrentNode)->balance)
{
case -1:
avlLeftBalanceWhenInsert(pCurrentNode, taller);
break;
case 0:
(*pCurrentNode)->balance = -1;
break;
case 1:
(*pCurrentNode)->balance = 0;
*taller = 0;
break;
}
}
}
else if (nCompRes < 0)
{
success = avl_tree_replace_loop(compare_func, free_data_func,
&((*pCurrentNode)->right), target_data, taller);
if (*taller != 0)
{
switch ((*pCurrentNode)->balance)
{
case -1 :
(*pCurrentNode)->balance = 0;
*taller = 0;
break;
case 0 :
(*pCurrentNode)->balance = 1;
break;
case 1 :
avlRightBalanceWhenInsert(pCurrentNode, taller);
break;
}
}
}
else
{
if (free_data_func != NULL)
{
free_data_func((*pCurrentNode)->data);
}
(*pCurrentNode)->data = target_data;
return 0;
}
return success;
}
int avl_tree_replace(AVLTreeInfo *tree, void *data)
{
int taller;
taller = 0;
return avl_tree_replace_loop(tree->compare_func, \
tree->free_data_func, &(tree->root), data, &taller);
}
static AVLTreeNode *avl_tree_find_loop(CompareFunc compare_func, \
AVLTreeNode *pCurrentNode, void *target_data)
{
int nCompRes;
nCompRes = compare_func(pCurrentNode->data, target_data);
if (nCompRes > 0)
{
if (pCurrentNode->left == NULL)
{
return NULL;
}
else
{
return avl_tree_find_loop(compare_func, \
pCurrentNode->left, target_data);
}
}
else if (nCompRes < 0)
{
if (pCurrentNode->right == NULL)
{
return NULL;
}
else
{
return avl_tree_find_loop(compare_func, \
pCurrentNode->right, target_data);
}
}
else
{
return pCurrentNode;
}
}
static void *avl_tree_find_ge_loop(CompareFunc compare_func, \
AVLTreeNode *pCurrentNode, void *target_data)
{
int nCompRes;
void *found;
nCompRes = compare_func(pCurrentNode->data, target_data);
if (nCompRes > 0)
{
if (pCurrentNode->left == NULL)
{
return pCurrentNode->data;
}
found = avl_tree_find_ge_loop(compare_func, \
pCurrentNode->left, target_data);
return found != NULL ? found : pCurrentNode->data;
}
else if (nCompRes < 0)
{
if (pCurrentNode->right == NULL)
{
return NULL;
}
else
{
return avl_tree_find_ge_loop(compare_func, \
pCurrentNode->right, target_data);
}
}
else
{
return pCurrentNode->data;
}
}
void *avl_tree_find(AVLTreeInfo *tree, void *target_data)
{
AVLTreeNode *found;
if (tree->root == NULL)
{
return NULL;
}
found = avl_tree_find_loop(tree->compare_func, \
tree->root, target_data);
return found != NULL ? found->data : NULL;
}
void *avl_tree_find_ge(AVLTreeInfo *tree, void *target_data)
{
void *found;
if (tree->root == NULL)
{
found = NULL;
}
else
{
found = avl_tree_find_ge_loop(tree->compare_func, \
tree->root, target_data);
}
return found;
}
static void avlLeftBalanceWhenDelete(AVLTreeNode **pTreeNode, int *shorter)
{
AVLTreeNode *leftsub;
AVLTreeNode *rightsub;
leftsub = (*pTreeNode)->left;
switch (leftsub->balance)
{
case -1:
(*pTreeNode)->balance = leftsub->balance = 0;
avlRotateRight (*pTreeNode, pTreeNode);
break;
case 0:
leftsub->balance = 1;
avlRotateRight(*pTreeNode, pTreeNode);
*shorter = 0;
break;
case 1:
rightsub = leftsub->right;
switch ( rightsub->balance )
{
case -1:
(*pTreeNode)->balance = 1;
leftsub->balance = 0;
break;
case 0 :
(*pTreeNode)->balance = leftsub->balance = 0;
break;
case 1 :
(*pTreeNode)->balance = 0;
leftsub->balance = -1;
break;
}
rightsub->balance = 0;
avlRotateLeft( leftsub, &((*pTreeNode)->left));
avlRotateRight(*pTreeNode, pTreeNode);
break;
}
}
static void avlRightBalanceWhenDelete(AVLTreeNode **pTreeNode, int *shorter)
{
AVLTreeNode *rightsub;
AVLTreeNode *leftsub;
rightsub = (*pTreeNode)->right;
switch (rightsub->balance)
{
case 1:
(*pTreeNode)->balance = rightsub->balance = 0;
avlRotateLeft(*pTreeNode, pTreeNode);
break;
case 0:
rightsub->balance = -1;
avlRotateLeft(*pTreeNode, pTreeNode);
*shorter = 0;
break;
case -1:
leftsub = rightsub->left;
switch (leftsub->balance)
{
case 1:
(*pTreeNode)->balance = -1;
rightsub->balance = 0;
break;
case 0:
(*pTreeNode)->balance = rightsub->balance = 0;
break;
case -1:
(*pTreeNode)->balance = 0;
rightsub->balance = 1;
break;
}
leftsub->balance = 0;
avlRotateRight(rightsub, &((*pTreeNode)->right));
avlRotateLeft(*pTreeNode, pTreeNode);
break;
}
}
static int avl_tree_delete_loop(AVLTreeInfo *tree, AVLTreeNode **pCurrentNode,\
void *target_data, int *shorter, AVLTreeNode *pDeletedDataNode)
{
int nCompRes;
bool result;
AVLTreeNode *leftsub;
AVLTreeNode *rightsub;
if (pDeletedDataNode != NULL)
{
if ((*pCurrentNode)->right == NULL)
{
pDeletedDataNode->data = (*pCurrentNode)->data;
leftsub = (*pCurrentNode)->left;
free(*pCurrentNode);
*pCurrentNode = leftsub;
*shorter = 1;
return 1;
}
nCompRes = -1;
}
else
{
nCompRes = tree->compare_func((*pCurrentNode)->data, target_data);
}
if (nCompRes > 0)
{
if ((*pCurrentNode)->left == NULL)
{
return 0;
}
result = avl_tree_delete_loop(tree, &((*pCurrentNode)->left), \
target_data, shorter, pDeletedDataNode);
if (*shorter != 0)
{
switch ((*pCurrentNode)->balance)
{
case -1:
(*pCurrentNode)->balance = 0;
break;
case 0:
(*pCurrentNode)->balance = 1;
*shorter = 0;
break;
case 1:
avlRightBalanceWhenDelete(pCurrentNode, shorter);
break;
}
}
return result;
}
else if (nCompRes < 0)
{
if ((*pCurrentNode)->right == NULL)
{
return 0;
}
result = avl_tree_delete_loop(tree, &((*pCurrentNode)->right), \
target_data, shorter, pDeletedDataNode);
if (*shorter != 0)
{
switch ((*pCurrentNode)->balance)
{
case -1:
avlLeftBalanceWhenDelete(pCurrentNode, shorter);
break;
case 0:
(*pCurrentNode)->balance = -1;
*shorter = 0;
break;
case 1:
(*pCurrentNode)->balance = 0;
break;
}
}
return result;
}
else
{
if (tree->free_data_func != NULL)
{
tree->free_data_func((*pCurrentNode)->data);
}
leftsub = (*pCurrentNode)->left;
rightsub = (*pCurrentNode)->right;
if (leftsub == NULL)
{
free(*pCurrentNode);
*pCurrentNode = rightsub;
}
else if (rightsub == NULL)
{
free(*pCurrentNode);
*pCurrentNode = leftsub;
}
else
{
avl_tree_delete_loop(tree, &((*pCurrentNode)->left), \
target_data, shorter, *pCurrentNode);
if (*shorter != 0)
{
switch ((*pCurrentNode)->balance)
{
case -1:
(*pCurrentNode)->balance = 0;
break;
case 0:
(*pCurrentNode)->balance = 1;
*shorter = 0;
break;
case 1:
avlRightBalanceWhenDelete(pCurrentNode, shorter);
break;
}
}
return 1;
}
*shorter = 1;
return 1;
}
}
int avl_tree_delete(AVLTreeInfo *tree, void *data)
{
int shorter;
if (tree->root == NULL)
{
return 0;
}
shorter = 0;
return avl_tree_delete_loop(tree, &(tree->root), data, &shorter, NULL);
}
static int avl_tree_walk_loop(DataOpFunc data_op_func, \
AVLTreeNode *pCurrentNode, void *args)
{
int result;
if (pCurrentNode->left != NULL)
{
result = avl_tree_walk_loop(data_op_func, \
pCurrentNode->left, args);
if (result != 0)
{
return result;
}
}
if ((result=data_op_func(pCurrentNode->data, args)) != 0)
{
return result;
}
/*
if (pCurrentNode->balance >= -1 && pCurrentNode->balance <= 1)
{
//printf("==%d\n", pCurrentNode->balance);
}
else
{
printf("==bad %d!!!!!!!!!!!!\n", pCurrentNode->balance);
}
*/
if (pCurrentNode->right != NULL)
{
result = avl_tree_walk_loop(data_op_func, \
pCurrentNode->right, args);
}
return result;
}
int avl_tree_walk(AVLTreeInfo *tree, DataOpFunc data_op_func, void *args)
{
if (tree->root == NULL)
{
return 0;
}
else
{
return avl_tree_walk_loop(data_op_func, tree->root, args);
}
}
static void avl_tree_count_loop(AVLTreeNode *pCurrentNode, int *count)
{
if (pCurrentNode->left != NULL)
{
avl_tree_count_loop(pCurrentNode->left, count);
}
(*count)++;
if (pCurrentNode->right != NULL)
{
avl_tree_count_loop(pCurrentNode->right, count);
}
}
int avl_tree_count(AVLTreeInfo *tree)
{
int count;
if (tree->root == NULL)
{
return 0;
}
count = 0;
avl_tree_count_loop(tree->root, &count);
return count;
}
int avl_tree_depth(AVLTreeInfo *tree)
{
int depth;
AVLTreeNode *pNode;
if (tree->root == NULL)
{
return 0;
}
depth = 0;
pNode = tree->root;
while (pNode != NULL)
{
if (pNode->balance == -1)
{
pNode = pNode->left;
}
else
{
pNode = pNode->right;
}
depth++;
}
return depth;
}
/*
static void avl_tree_print_loop(AVLTreeNode *pCurrentNode)
{
printf("%ld left: %ld, right: %ld, balance: %d\n", pCurrentNode->data,
pCurrentNode->left != NULL ? pCurrentNode->left->data : 0,
pCurrentNode->right != NULL ? pCurrentNode->right->data : 0,
pCurrentNode->balance);
if (pCurrentNode->left != NULL)
{
avl_tree_print_loop(pCurrentNode->left);
}
if (pCurrentNode->right != NULL)
{
avl_tree_print_loop(pCurrentNode->right);
}
}
void avl_tree_print(AVLTreeInfo *tree)
{
if (tree->root == NULL)
{
return;
}
avl_tree_print_loop(tree->root);
}
*/