平衡二叉树操作(查询树高、平衡因子、删除节点、插入节点)

这是本人课程设计的题目,由于对于平衡二叉树的删除操作在大部分数据结构的书上没有介绍,网上此类操作的代码也少,因此,我把我做的贴出来晒一晒

 

typedef struct BBT
{
 int data;              //节点的数据域
 int bf;                //平衡因子
 BBT * lchild,*rchild;  //节点的左、右孩子指针
}* B_Point,BBT;            //将B_Point定义为结构体指针
B_Point Root;              //定义全树的树根指针全局变量
//左旋转
void BBT_L_Rotate(B_Point & root)            // root为需要旋转的子树树根指针 
{
 B_Point rc=root->rchild;                 // 将rc指身树的树根的右子树
 root->rchild=rc->lchild;                 // 将树的右子树的左子树挂到树根的右子树上
 rc->lchild=root;                         // 将root所指树挂到rc的左子树上
 root=rc;                                 //更新树根
}
// 右旋转
void BBT_R_Rotate(B_Point & root)             // root为需要右旋的子树树根指针
{
 B_Point lc=root->lchild;                  //lc指向root的右子树根
 root->lchild=lc->rchild;                  //lc的右子树连接到root的左子树上
 lc->rchild =root;                         //root连接到lc的右子树
 root=lc;                                  //更新树根    
}
//左平衡处理
void LeftBalance(B_Point & root)     
{
 B_Point lc=root->lchild,rc=NULL;          //lc指向root的左子树
 if(lc->bf==1)                             //LL型
 {
  root->bf=lc->bf=0;                    //更新平衡因子
  BBT_R_Rotate(root);                   //root作为根进行右旋转
 }
 else if(lc->bf==-1)                       //LR型
 {
  rc=lc->rchild;                        //将rc指向lc的右子树
  if(rc->bf==1)                         //检查rc的平衡因子,并做相应的处理
  {
   root->bf=-1;
   lc->bf=0;
  }
  else if(rc->bf==0)
  {
   root->bf=0;
   lc->bf=0;
  }
  else
  {
   root->bf =0;
   lc->bf =1;
  }
  rc->bf=0;
  BBT_L_Rotate(root->lchild);               //以root的左子树根结点为根进行左旋转处理
  BBT_R_Rotate(root);                       //以root作为根进行旋转处理
 }
 else  //此情况只可能出现在删除中     此时lc->bf等于0      
 {//修改平衡因子
  rc=lc->rchild;
  if(rc->bf==1)
  {
   root->bf=-1;
   lc->bf=1;
   rc->bf=1;
  }
  else if(rc->bf==0)
  {
   root->bf=1;
   lc->bf=1;
   rc->bf=1;
  }
  else
  {
   root->bf =0;
   lc->bf =2;//设为2方便后面识别
   rc->bf=0;
  }
  
  BBT_L_Rotate(root->lchild);
  BBT_R_Rotate(root);
  if(root->lchild->bf==2)        //此时再追加一次旋转
  {
   root->lchild->bf=root->lchild->lchild->bf=0;
   BBT_R_Rotate(root->lchild);
  }
 }
}
//右平衡处理
void RightBalance(B_Point & root)       
{
 B_Point rc=root->rchild,lc=NULL;
 if(rc->bf==-1)                     //RR型
 {
  rc->bf=root->bf=0;
  BBT_L_Rotate(root);
 }
 else if(rc->bf==1)                 //RL型
 {
  lc=rc->lchild;
  if(lc->bf==1)
  {
   rc->bf=0;
   root->bf =-1;
  }
  else if(lc->bf==0)
  {
   root->bf=rc->bf=0;
  }
  else
  {
   root->bf =1;
   rc->bf =0;
  }
  lc->bf=0;
  BBT_R_Rotate(root->rchild);
  BBT_L_Rotate(root);
 }
 else //此情况只可能出现在删除过程中   此时rc->bf等于0
 {
  lc=rc->lchild;
  if(lc->bf==1)                       //检查lc的平衡因子,并进行相应处理
  {
   rc->bf=-2;
   root->bf =0;
   lc->bf=0;
  }
  else if(lc->bf==0)
  {
   root->bf=0;
   rc->bf=-1;
   lc->bf=-1;
  }
  else
  {
   root->bf =1;
   rc->bf =-1;
  }
  
  BBT_R_Rotate(root->rchild);
  BBT_L_Rotate(root);
  if(root->rchild->bf==-2)//此时由于树并不平等,须追加一次旋转
  {
   root->rchild->bf=root->rchild->rchild->bf=0;//更新平衡因子
   BBT_L_Rotate(root->rchild);
  }
 }
}

// 插入操作
bool BBT_Insert(B_Point & now,bool & taller,int data)   //now表示当前子树的根,taller为真时表示到目前为子树层数增加,为假则没增加
{                                                       //插入成功返回真,否则返回假
 bool result=false;                               //result表示插入的结果,插入成功为真,否则为假
 if(!now)                                         //now指针为空时在当前指针处插入新节点
 {
  now=new BBT;                                 //新建一个节点
  now->bf=0;                                   //节点初始化操作,平衡因子赋为0
  now->data=data;                              //将待插入的数据置入新节点的数据域中
  now->lchild=now->rchild=NULL;                //将新节点的左右子树指针置为空
  taller=true;                                 //添加新节点,默认为增加子树的高度
  return true;                                 //插入成功,返回真
 }
 else if(data<now->data)                          //当前待插入数据小于当前子树根的数据
 {
  result=BBT_Insert(now->lchild,taller,data);   //递归,以当前树根的左子树根为新子树树根调用插入函数
  if(taller)                                    //判断taller的值,为真时插入操作一定成功,并且进入平衡处理
  {                                             //检查插入前当前树根的平衡因子
   if(now->bf==-1)                           
   {
    now->bf=0;                            //插入后不改变此子树高度,无须进一步平衡处理,修改平衡因子即可
    taller=false;                         //子树高不改变,taller置为假
   }
   else if(now->bf==0)
   {
    now->bf =1;                            //插入后子树高增加,但此子树的局部平衡没被破坏,修改平衡因子即可
    taller=true;                           //树高增加,taller置为真
   }
   else
   {
    LeftBalance(now);                      //插入后此子树局部平衡被破坏,需调用左平衡处理函数使之平衡
    taller=false;                          //平衡处理后此子树高度不会增加,taller置为假
   }
  }
 }
 else if(data>now->data)                             //待插入数据大于当前子树根节点数据
 {
  result=BBT_Insert(now->rchild,taller,data);     //以下同上
  if(taller)
  {
   if(now->bf==-1)
   {
    RightBalance(now);
    taller=false;
   }
   else if(now->bf==0)
   {
    now->bf=-1;
    taller=true;
   }
   else
   {
    now->bf=0;
    taller=false;
   }
  }
 }
 return result;                                       //返回插入情况
}
void BBT_Del(B_Point & root,int data,bool & shorter,bool & suc,bool & del,bool & leaf)
{//suc表示删除成功,shorter表示子树高度减小与否,del表示在本次中删除,leaf表示删除的节点是否为叶子节点
 B_Point p,f;
 if(!root)                                         //root为空时表示未找到该数据,suc赋为假
  suc=false;     
 else if(root->data==data)                         //如果待删除数据与当前子树根节点数据相等,即待删除节点为root
 {
  if(root->lchild==NULL&&root->rchild==NULL)    //检查是否为叶子节点
  {
   leaf=del=true;                            //将leaf、del赋为真,向上层传递删除节点信息
   if(Root==root) Root=NULL;                 //如果删除的节点是全树的根节点,则将全树根节点指针置为空
   delete root;                              //删除该节点
   shorter=true;                             //当前子树高度减小
  }
  else                             //不是叶子节点
  {
   if(root->lchild==NULL)//左子树为空时  (左为空右一定不为空,否则就是叶子)
   {
    p=root;                  // 将p指向root
    root=root->rchild;       // 将root的右子树挂到root上
    delete(p);               // 删除p所指节点
    shorter=true;            // 当前子树高度减小
   }
   else //左子树不为空时
   {
    p=f=root->lchild;         // 将p,f指向root的左孩子
    while(p->rchild)          // 左转向右到底
    {
     f=p;                  //f为p的前驱
     p=p->rchild;          //p向右子树走
    }
    if(p==f)                      //此时p没有右子树
    {//将root的左子树根节点补上来做新的root,删除以前的root
     p=root;                   //将p指向root
     root=f;                   //将root指向f
     root->rchild=p->rchild;   //将p的右子树挂到新root的右子树
     if(p->bf==0)//检查原树根的平衡因子
     {
      shorter=false;        //当前树高度没有减小
      root->bf=-1;          //更新当前树根的平衡因子
     }
     else if(p->bf==1)         
     {
      shorter=true;         //当前树高度减小
      root->bf=0;           //更新平衡因子
     }
     else
     {
      root->bf=p->bf-1;     //更新平衡因子
         RightBalance(root);   //此时相当于右子树增加节点
      shorter=true;         //当前树高度减小
     }
     delete p;                 //删除待删节点
    }
    else
    {// 此时待删除节点与左子树最右边的节点更换,再删除最右边的节点
     root->data=p->data;       //更换两节点的数据
     f->rchild=p->lchild;      //将p的左子树挂到其前驱f的右子树上
     delete p;                 //删除p所指的结点
     if(f->bf==0)              //检查f平衡因子
     {
      shorter=false;        //当前以f为根的子树高没发生变化
      f->bf=1;              //更新f的平衡因子
     }
     else if(f->bf==1)
     {
      LeftBalance(root->lchild);//当前以f为根的子树进行左平衡处理(相当于左边增加节点)
      shorter=true;
     }
     else
     {
      shorter=true;           //以f 为根的子树平衡未被破坏,但高度减小
      f->bf=0;                //更新f的平衡因子
     }
     if(shorter)                 //当以f 为根的子树树高减小时,进行平衡处理
     {//此这程类似上述过程
      if(root->bf==0)
      {
       shorter=false;
       root->bf=-1;
      }
      else if(root->bf==1)
      {
       shorter=true;
       root->bf=0;
      }
      else
      {
       RightBalance(root);//相当于右边增加
       shorter=true;
      }
     }
    }
   }
  }
 }
 else if(data<root->data)        //待删除的数据小于当前树根数据
 {
  BBT_Del(root->lchild,data,shorter,suc,del,leaf);   //递归,在以root左子树根中继续调用本函数
  if(del&&leaf)                       //删除的是叶子节点
  {
   root->lchild=NULL;              //当前树根左子树指针置为空
   del=false;                      //更新 del的值
  }
  if(shorter)                        //shorter为真,树高减小,分析平衡因子,进行平衡处理
  {
   if(root->bf==0)
   {
    root->bf=-1;
    shorter=false;
   }
   else if(root->bf==1)
   {
    root->bf=0;
    shorter=true;
   }
   else
   {
    RightBalance(root);
    shorter=true;
   }
  }
 }
 else//待删除的数据大于当前树根数据
 {
  BBT_Del(root->rchild,data,shorter,suc,del,leaf);
  if(del&&leaf)
  {
   del=false;
   root->rchild=NULL;
  }
  if(shorter)
  {
   if(root->bf==0)
   {
    root->bf=1;
    shorter=false;
   }
   else if(root->bf==1)
   {
    LeftBalance(root);//
    shorter=true;
   }
   else
   {
    root->bf=0;
    shorter=true;
   }
  }
 }
}
 //查找平衡因子
int Find_BF(B_Point root,int data)            
{
 if(!root)
  return 100;//100表示不存在,以用表示查找失败
 if(data==root->data)  
  return root->bf;                        //找到该数据节点,返回平衡因子
 else if(data<root->data)                    //否则递归调用
  return Find_BF(root->lchild,data);
 else return Find_BF(root->rchild,data);
}
//中序遍历
void Traverse(B_Point root)
{
 if(root)//当前根节点不为空
 {
  Traverse(root->lchild);           //在左子树中递归
  printf("%d ",root->data);         //显示当前节点为数据
  Traverse(root->rchild);           //在右子树中递归
 }
}
//获取树高
void GetTreeHeight(B_Point root,int TreeHeight,int & MaxHeight)
{
 if(root)                                               //当前根节点不为空
 {
  TreeHeight++;                                      //树高加1
  if(TreeHeight>MaxHeight) MaxHeight=TreeHeight;     //与树高最大值比较
  GetTreeHeight(root->lchild,TreeHeight,MaxHeight);  //在左子树中递归
  GetTreeHeight(root->rchild,TreeHeight,MaxHeight);  //在右子树中递归
 }
}

 

    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/tomliuchangsha/article/details/5275016
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞