//平衡二叉树是为了解决二叉排序树中某些极端的现象而产生的!
//平衡二叉树( Balanced Binary Tree 或 Height-Balanced Tree )又称AVL树。
//特点:左右子树的深度之差的绝对值不超过1。//平衡二叉树和二叉排序树的操作只有Insert和Delete不同(因为要调整平衡因子).
#include < stdio.h >
#include < stdlib.h >
//#include < string.h >#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status ;//#ifndef Boolean
//#define unsigned int Boolean
//#endif//-----对数值型关键字的比较--------//
#define EQ( a , b ) ( ( a ) == ( b ) )
#define LT( a , b ) ( ( a ) < ( b ) )
#define LQ( a , b ) ( ( a ) <= ( b ) )//-----字符串型关键字的比较--------//
//#define EQ( a , b ) ( !strcmp( a , b ) )
//#define LT( a , b ) ( strcmp( a , b ) < 0 )
//#defien LQ( a , b ) ( strcmp( a , b ) <= 0 )#define LH 1 //左高(左子树的深度减去右子树的深度)
#define EH 0 //等高
#define RH -1 //右高typedef int KeyType ; //定义关键字的类型
typedef struct {
KeyType key ;
} SElemType ; //数据结构体可以自行扩充typedef struct BSTNode {
SElemType data ;
int bf ; //结点的平衡因子
struct BSTNode *lchild , *rchild ;
} BSTNode , *BSTree ;Status InitBST( BSTree *T ) ;
Status DestroyBST( BSTree *T ) ;
Status SearchBST( BSTree T , KeyType key , BSTree f , BSTree *p ) ;
Status InsertAVL( BSTree *T , SElemType e , int *taller ) ;
//Status Delete( BSTree *p ) ;
//Status DeleteBST( BSTree *T , KeyType key ) ;
Status TraverseBST( BSTree T , void ( *Visit )( SElemType e ) ) ;
void visit( SElemType e ) ;void R_Rotate( BSTree *p ) ;
void L_Rotate( BSTree *p ) ;
void LeftBalance( BSTree *T ) ;
void RightBalance( BSTree *T ) ;
//------------------------ Basic Functions!---------------------------//
Status InitBST( BSTree *T )
{
*T = NULL ;
return OK ;
}Status DestroyBST( BSTree *T ) //先释放左右子树,然后再释放根结点
{
if( !( *T ) ) //为空树
return ERROR ;if( ( *T )->lchild )
{
DestroyBST( &( ( *T )->lchild ) ) ;
}
if( ( *T )->rchild )
{
DestroyBST( &( ( *T )->rchild ) ) ;
}
free( ( *T ) ) ;
( *T ) = NULL ; //释放指针后,最好将其指向空!因为我们仅仅只是释放其中的资源,并没有释放指针,因为指针就像变量一样,被定义了后就不能释放的!return OK ;
}Status SearchBST( BSTree T , KeyType key , BSTree f , BSTree *p ) //Take care! 指针f指向T的双亲,其初始调用值为NULL.
{
if( !T ) //查找不成功
{
*p = f ;
return FALSE ;
}
else //查找成功
{
if( EQ( key , T->data.key ) )
{
( *p ) = T ; //如果查找到,则指针p指向该数据元素结点
return TRUE ;
}
else
{
if( LT( key , T->data.key ) )
{
return SearchBST( T->lchild , key , T , p ) ;
}
else
{
return SearchBST( T->rchild , key , T , p ) ;
}
}
}return OK ;
}//--------------------------------------------------------------------------------//
void R_Rotate( BSTree *p ) //对照图(a)理解
{ // 对以*p为根的二叉排序树作右旋处理,处理之后p指向新的根结点,即旋转处理之前的左子树的根结点
BSTree lc ;lc = ( *p )->lchild ; //lc指向的*p的左子树根结点
( *p )->lchild = lc->rchild ; //lc的右子树挂接*p的左子树
lc->rchild = ( *p ) ;
( *p ) = lc ; //p指向新的根结点
}void L_Rotate( BSTree *p ) //左旋,处理同上相似
{
BSTree rc ;rc = ( *p )->rchild ;
( *p )->rchild = rc->lchild ;
rc->lchild = ( *p ) ;
( *p ) = rc ;
}Status InsertAVL( BSTree *T , SElemType e , int *taller )
{ //若在平衡二叉排序树中T不存在和e有相同关键字的结点,则插入一个数据元素e的新结点!若因插入而失去平衡,则做平衡旋转处理,taller反映T长高与否if( !( *T ) )
{
( *T ) = ( BSTree )malloc( sizeof( BSTNode ) ) ;
( *T )->data = e ;
( *T )->lchild = ( *T )->rchild = NULL ;
( *T )->bf = EH ;
*taller = TRUE ; //插入新结点,树长"高",taller置为TRUE.
}
else
{
if( EQ( e.key , ( *T )->data.key ) )
{
*taller = FALSE ; //存在和e相同关键字的结点,故不再插入.
return 0 ;
}
if( LQ( e.key , ( *T )->data.key ) )
{
if( !InsertAVL( &( *T )->lchild , e , taller ) )
return 0 ;
if( taller ) //已插入到左子树中且左子树"长高"
{
switch( ( *T )->bf )//检查*T的平衡度
{
case LH:
{
LeftBalance( T ) ; *taller = FALSE ; //原本左子树就比右子树高,所以需要左平衡处理。
break ;
}
case EH:
{
( *T )->bf = LH ; *taller = TRUE ;
break ;
}
case RH:
{
( *T )->bf = EH ; *taller = FALSE ;
break ;
}
} // switch
}
}
else
{
if( !InsertAVL( &( *T )->rchild , e , taller ) )
return 0 ;
if( taller ) //已插入到右子树中且右子树"长高"
{
switch( ( *T )->bf )//检查*T的平衡度
{
case LH:
{
( *T )->bf = EH ; *taller = FALSE ; //原本左子树就比右子树高,所以需要左左平衡处理。
break ;
}
case EH:
{
( *T )->bf = RH ; *taller = TRUE ;
break ;
}
case RH:
{
RightBalance( T ) ; *taller = FALSE ;
break ;
}
} // switch
}
} // else
} //else
return 1 ;
}void LeftBalance( BSTree *T )
{ //对以指针T所指结点为根的二叉树作左平衡旋转处理,本算法结束时,指针T指向新的根结点
BSTree lc , rd ;lc = ( *T )->lchild ;
switch( lc->bf )
{
case LH: //新结点插入在*T的左孩子的左子树上,要作单右旋处理
{
( *T )->bf = lc->bf = EH ;
R_Rotate( T ) ;
break ;
}
case RH: //新结点插入在*T的左孩子的右子树上,要作但双旋处理
{
rd = lc->rchild ; //rd指向*T的左孩子的右子树根.
switch( rd->bf ) //修改*T及左孩子的平衡因子
{
case LH: ( *T )->bf = RH ; lc->bf = EH ; break ; //还需理解!!!!!!
case EH: ( *T )->bf = lc->bf = EH ; break ;
case RH: ( *T )->bf = EH ; lc->bf = LH ; break ;
} // rd->bf
rd->bf = EH ;
L_Rotate( &( *T )->lchild ) ;
R_Rotate( T ) ;
}
} // lc->bf
}void RightBalance( BSTree *T )
{
BSTree rc , ld ;rc = ( *T )->rchild ;
switch( rc->bf )
{
case RH:
{
( *T )->bf = rc->bf = EH ;
L_Rotate( T ) ;
break ;
}
case LH:
{
ld = rc->lchild ;
switch( ld->bf )
{
case RH: ( *T )->bf = LH ; rc->bf = EH ; break ;
case EH: ( *T )->bf = rc->bf = EH ; break ;
case LH: ( *T )->bf = EH ; rc->bf = RH ; break ;
} // rd->bf
ld->bf = EH ;
R_Rotate( &( *T )->rchild ) ;
L_Rotate( T ) ;
}
} // lc->bf
}//--------------------------------------------------------------------------------//
/*
Status Delete( BSTree *p ) //c从二叉排序树中删除结点p,并重接它的左或右子树
{
BSTree q , s ;if( !( *p )->rchild ) //右子树为空,只需要重接它的左子树
{
q = *p ;
*p = ( *p )->lchild ;
free( q ) ;
}
else
{
if( !( *p )->lchild )
{
q = *p ;
( *p ) = ( *p )->rchild ;
free( q ) ;
}
else //左右子树均不空
{
q = ( *p ) ;
s = ( *p )->lchild ;
while( s->rchild )
{
q = s ; s = s->rchild ;//转左,然后向右到尽头
}
( *p )->data = s->data ; //s指向被删结点的“前驱”
if( q != ( *p ) )
{
q->rchild = s->lchild ;//重接*q的右子树
}
else
{
q->lchild = s->lchild ;//重接*q的右子树
}
free( s ) ;
}
}return TRUE ;
}Status DeleteBST( BSTree *T , KeyType key )
{
if( !( *T ) )
return FALSE ;
else
{
if( EQ( key , ( *T )->data.key ) )
{
return Delete( T ) ;
}
else
{
if( LT( key , ( *T )->data.key ) )
return DeleteBST( &( *T )->lchild , key ) ;
else
return DeleteBST( &( *T )->rchild , key ) ;
}
}
return OK ;
}
*/
Status TraverseBST( BSTree T , void ( *Visit )( SElemType e ) )
{
if( !T ) //树为空树
return ERROR ;TraverseBST( T->lchild , Visit ) ;
Visit( T->data ) ;
TraverseBST( T->rchild , Visit ) ;return OK ;
}void visit( SElemType e )
{
printf( "%5d" , e.key ) ;
}//---------------------------------------------------------------//
int main( )
{
BSTree T , f , p ;
int i , taller ;
SElemType e[ 5 ] = { 13 , 24 , 37 , 90 , 53 } ;InitBST( &T ) ;
for( i = 0 ; i < 5 ; ++ i )
{
InsertAVL( &T , e[ i ] , &taller ) ;
}f = NULL ;
SearchBST( T , 90 , f , &p ) ;
printf( "%5d\n" , p->data.key ) ;
TraverseBST( T , visit ) ;DestroyBST( &T ) ;
printf( "\n" ) ;
return 0 ;
}
好吧!我承认当时我真的没有勇气把与InertAVL相对应的DeleteAVL完成!不过,现在,不清楚!呵呵……有勇气的、想挑战一下的同学,可以试一下哦!加油!