第九章(4).平衡二叉树

//平衡二叉树是为了解决二叉排序树中某些极端的现象而产生的!
//平衡二叉树( 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完成!不过,现在,不清楚!呵呵……有勇气的、想挑战一下的同学,可以试一下哦!加油!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值