算法描述:
在平衡的二叉排序树T上插入一个关键码为kx的新元素,递归算法可描述如下:
㈠ 若T为空树,则插入一个数据元素为kx的新结点作为T的根结点,树的深度增1;
㈡ 若kx和T的根结点关键码相等,则不进行插入;
㈢ 若kx小于T的根结点关键码,而且在T的左子树中不存在与kx有相同关键码的结点,则将新元素插入在T的左子树上,并且当插入 之后的左子树深度增加1时,分别就下列情况进行处理:
⑴ T的根结点平衡因子为-1(右子树的深度大于左子树的深度),则将根结点的平衡因子更改为0,T的深度不变;
⑵ T的根结点平衡因子为0(左、右子树的深度相等),则将根结点的平衡因子更改为1,T的深度增加1;
⑶ T的根结点平衡因子为1(左子树的深度大于右子树的深度),则若T的左子树根结点的平衡因子为1,需进行单向右旋平衡处理并且在右旋 处理之后,将根结点和其右子树根结点的平衡因子更改为0,树的深度不变;若T的左子树根结点平衡因子为-1,需进行先左后右 双向旋转平衡处理,并且 在旋转处理之后,修改根结点和其左、右子树根结点的平衡因子,树的深度不变。
㈣ 若kx大于T的根结点关键码,而且在T的右子树中不存在与kx有相同关键码的结点,则将新元素插入在T的右子树上并且当插入之后的右子树深度增加1时,分别就不同情况处理之。其处理操作和 ㈢ 中所述相对称。
动画演示:
http://www.cnblogs.com/abatei/archive/2008/11/17/1335031.html
牛人博客一篇,完美的对称化:
http://blog.csdn.net/happycock/article/details/20874
code:
/*
*设计思路:
1.通过void *表示任意类型的数据
2.通过为插入函数提供比较函数,实现任意数据的插入
3.本头文件实现的是适合任意类型的平衡二叉树的数据结构,目前仅支持字符串和整型数据的平衡二叉树;
若需要其他类型,定义相关的比较函数即可;
4.平衡二叉树构造的基本思想:节点的平衡因子只能是-1,0,1;在插入造成不平衡时,需要对距离插入节点最近的不平衡节点做旋转处理,上面的则不作处理;
5.插入的基本操作是左旋和右旋,左右旋和右左旋也能划分为这两种操作,关键在于旋转后平衡因子的确定
*/
#include <stdlib.h>
#include <string.h>
#define LH 1
#define EH 0
#define RH -1
typedef int (*COMPARE_FUNC)(void *, void *);
typedef struct avlnode{
void *data;
struct avlnode *lchild, *rchild;
int bf;
}AVLNode, *AVLTree;
int compare_string(void *str1, void *str2)
{//call back func
char *s1 = (char *)str1;
char *s2 = (char *)str2;
return strcmp(s1,s2);
}
int compare_int(void *var1, void *var2)
{
int v1 = *(int *)var1;
int v2 = *(int *)var2;
return v1 - v2;
}
void R_Rotate(AVLTree *root)
{//向右旋转,适合LL型
AVLTree lchild = (*root)->lchild;
(*root)->lchild = lchild->rchild;
lchild->rchild = *root;
*root = lchild;
}
void L_Rotate(AVLTree *root)
{
AVLTree rchild = (*root)->rchild;
(*root)->rchild = rchild->lchild;
rchild->lchild = *root;
(*root) = rchild;
}
void RightBalance(AVLTree *root)
{//bf == -2
AVLTree rchild = (*root)->rchild;
AVLTree rlchild;
switch(rchild->bf)
{
case RH:
rchild->bf = EH;
(*root)->bf = EH;
L_Rotate(root);
break;
case LH:
rlchild = rchild->lchild;
switch(rlchild->bf)
{
case RH:
(*root)->bf = LH;
rchild->bf = EH;
break;
case EH:
(*root)->bf = EH;
rchild->bf = EH;
break;
case LH:
(*root)->bf = EH;
rchild->bf = RH;
break;
}
rlchild->bf = EH;
R_Rotate(&((*root)->rchild));
L_Rotate(root);
default:
break;
}
}
void LeftBalance(AVLTree *root)
{//bf == 2
AVLTree lchild = (*root)->lchild;
AVLTree lrchild;
switch(lchild->bf)
{
case LH://LL型 root bf 2 lchild bf 1
lchild->bf = EH;
(*root)->bf = EH;
R_Rotate(root);
break;
case RH://LR型
lrchild = lchild->rchild;
switch(lrchild->bf)
{
case LH:
(*root)->bf = RH;
lchild->bf = EH;
break;
case EH:
(*root)->bf = EH;
lchild->bf = EH;
break;
case RH:
(*root)->bf = EH;
lchild->bf = LH;
break;
}
lrchild->bf = EH;
L_Rotate(&((*root)->lchild));
R_Rotate(root);
default:
break;
}
}
int shorter = 0;
void RightBalanceD(AVLTree *root)
{
AVLTree rchild = (*root)->rchild;
AVLTree rlchild;
switch(rchild->bf)
{
case RH:
(*root)->bf = rchild->bf = EH;
R_Rotate(root);
break;
case EH:
(*root)->bf = RH;
rchild->bf = RH;
L_Rotate(root);
shorter = 0;
break;
case LH:
rlchild = rchild->lchild;
switch(rlchild->bf)
{
case LH:
(*root)->bf = LH;
rchild->bf = EH;
break;
case EH:
(*root)->bf = EH;
rchild->bf = EH;
break;
case RH:
(*root)->bf = EH;
rchild->bf = RH;
break;
}
rlchild->bf = EH;
R_Rotate(&((*root)->rchild));
L_Rotate(root);
}
}
void LeftBalanceD(AVLTree *root)
{
AVLTree lchild = (*root)->lchild;
AVLTree lrchild;
switch(lchild->bf)
{
case LH:
(*root)->bf = lchild->bf = EH;
R_Rotate(root);
break;
case EH:
(*root)->bf = LH;
lchild->bf = RH;
R_Rotate(root);
break;
case RH:
lrchild = lchild->rchild;
switch(lrchild->bf)
{
case RH:
(*root)->bf = EH;
lchild->bf = EH;
shorter = 0;
break;
case EH:
(*root)->bf = EH;
lchild->bf = EH;
shorter = 1;
break;
case LH:
(*root)->bf = RH;
lchild->bf = EH;
shorter = 1;
break;
}
lrchild->bf = EH;
L_Rotate(&((*root)->lchild));
R_Rotate(root);
}
}
int AVLDelete(AVLTree *root, void *data, COMPARE_FUNC compare)
{
int success = 0;
int ret;
if(NULL != *root)
{
ret = compare(data, (*root)->data);
if( ret == 0)
{
if(NULL != (*root)->lchild && NULL != (*root)->rchild)
{
AVLTree q,r;
void *temp;
//将左子树的最下面的右子树作为其替身,然后删掉,递归进行
q = (*root)->lchild;
r = q;
while(q)
{
r = q;
q = q->rchild;
}
temp = (*root)->data;
(*root)->data = r->data;
r->data =temp;
AVLDelete(&(*root)->lchild, data, compare);
if(1 == shorter)
{
switch((*root)->bf)
{
case LH:
(*root)->bf = EH;
break;
case EH:
(*root)->bf = RH;
break;
case RH:
RightBalanceD(root);
break;
}//switch
}//if shorter
}//if NULL
else
{
//至少有一个子树为空
AVLTree p = *root;
*root = ((*root)->lchild != NULL)?(*root)->lchild:(*root)->rchild;
free(p->data);
free(p);
success = 1;
shorter = 1;
}
}//if compare
else if(ret < 0)
{
success = AVLDelete(&((*root)->lchild), data, compare);
if(shorter == 1)
{
switch((*root)->bf)
{
case LH:
(*root)->bf = EH;
shorter = 0;
break;
case EH:
(*root)->bf = RH;
break;
case RH:
RightBalanceD(root);
break;
}//switch
}//if
}//else if
else if(ret > 0)
{
success = AVLDelete(&((*root)->rchild), data, compare);
if(shorter == 1)
{
switch((*root)->bf)
{
case LH:
LeftBalanceD(root);
break;
case EH:
(*root)->bf = LH;
break;
case RH:
(*root)->bf = EH;
shorter = 0;
break;
}//switch
}//if
}//else if
}//if root
return success;
}
/*
output:
return 1:success
return 0:already exist
return -1:unexpected err
input:
root:这棵平衡二叉树的根节点;
data:欲插入的数据指针;
len:插入数据的大小;
compare:插入数据类型的比较函数;
*/
int taller= 0;
int AVLInsert(AVLTree *root, void *data,int len, COMPARE_FUNC compare)
{
int ret;
if(NULL == (*root))
{
(*root) = (AVLTree)malloc(sizeof(AVLNode));
if(NULL == (*root))
return -1;
(*root)->data = (void *)(char *)malloc(len);
if(NULL == (*root)->data)
return -1;
memcpy((*root)->data, data, len);
(*root)->lchild = NULL;
(*root)->rchild = NULL;
(*root)->bf = EH;
taller = 1;
return 1;
}
//the tree is not empty
ret = compare(data, (*root)->data);
//already exist
if(0 == ret)
return 0;
else if(ret > 0)
{
ret = AVLInsert(&((*root)->rchild), data, len, compare);
if(-1 == ret)
return -1;
else if( 0 == ret)
return 0;
if(taller != 0)
{
switch((*root)->bf)
{
case LH:
(*root)->bf = EH;
taller = 0;
break;
case EH:
(*root)->bf = RH;
taller = 1;
break;
case RH:
RightBalance(root);
taller = 0;
break;
default:
break;
}
}
}
else
{
ret = AVLInsert(&((*root)->lchild), data, len, compare);
if(-1 == ret)
return -1;
else if( 0 == ret)
return 0;
if(taller != 0)
{
switch((*root)->bf)
{
case RH:
(*root)->bf = EH;
taller = 0;
break;
case EH:
(*root)->bf = LH;
taller = 1;
break;
case LH:
LeftBalance(root);
taller = 0;
break;
default:
break;
}
}
}
return 1;
}
/*
*free the tree
*/
void FreeTree(AVLTree *root)
{
if(NULL != *root)
{
FreeTree(&((*root)->lchild));
FreeTree(&((*root)->rchild));
free((*root)->data);
free(*root);
*root = NULL;
}
}
/*
search for the data in the avltree
input:
root: root of the searching tree
data:data to search
compare:compare func for data
output:
NULL:not find
!NULL: find the result
*/
AVLNode *SearchAVLNode(AVLTree root, void *data, COMPARE_FUNC compare)
{
int ret;
if(NULL != root)
{
ret = compare(root->data, data);
if(0 == ret)
return root;
else if(ret > 0)
return SearchAVLNode(root->lchild, data, compare);
else
return SearchAVLNode(root->rchild, data, compare);
}
return NULL;
}
void in_order_tranverse(AVLTree root, int type)
{
if(root)
{
in_order_tranverse(root->lchild, type);
if(1 == type)//string
printf("%s %d\n", (char *)(root->data), root->bf);
else if(2 == type)
printf("%d %d\n", *(int *)(root->data), root->bf);
in_order_tranverse(root->rchild, type);
}
}
void avltree_test()
{
AVLTree string_root = NULL;
AVLTree int_root = NULL;
char *str[] = {"file", "edit", "view", "qt", "project", "build", "debug", "tools","window", "community", "help"};
int num[]={34,24,67, 1, 56, 83, 27, 98};
int i;
for(i = 0; i < sizeof(str)/sizeof(char *); i++)
AVLInsert(&string_root, (void *)str[i], strlen(str[i]) +1, compare_string);
for(i= 0; i< sizeof(num)/sizeof(int *); i++)
AVLInsert(&int_root, (void *)(num + i), sizeof(int), compare_int);
AVLDelete(&string_root, "qt", compare_string);
in_order_tranverse(string_root, 1);
in_order_tranverse(int_root, 2);
if(SearchAVLNode(string_root, "project", compare_string))
printf("Find project\n");
else
printf("Not find project\n");
if(SearchAVLNode(string_root, "home", compare_string))
printf("Find home\n");
else
printf("Not find home\n");
if(SearchAVLNode(int_root, num + 3, compare_string))
printf("Find %d\n", *(num + 3));
else
printf("Not find %d\n", *(num + 3));
//FreeTree(&string_root);
FreeTree(&int_root);
}