关闭

平衡树构造算法

565人阅读 评论(0) 收藏 举报

构造平衡树算法:

  我们知道, 二叉搜索树的平均效率是O(lgN), 以2为底的. 但是,如果不是平衡树的话, 这个效率就有可能很差的. 举一个最简单的例子: 1, 2, 3, 4, 5, 6, 以普通二叉树方式构造,最终树的样子是每个节点的右孩子为下一个节点, 形成一个链表状结构:1->2->3->4->5->6,这样搜索效率就是O(N)的. 所以, 为了效率, 在创建树时, 要进行平衡处理.

  如何平衡, 大致分为四种:

  1. 单向右旋转:假设由于在节点A的左子树上插入了新节点而引起了节点A的平衡因子由1变成了2(说明:平衡因子为 节点的左子树高度 - 节点右子树高度, 为1,说明左子树树高比右子树高1, 为-1, 说明右子树高度比左子树高1, 为0表示两边相等, 为理想状态.当平衡因子绝对值>=2时, 需要旋转), 至使节点A失去平衡,需要单向右旋操作:

平衡树构造算法

2.单向左旋转: 由于在节点A的右子树上插入新节点而引起的节点A失去平衡, 需要单向左旋转, 如下图所示:

平衡树构造算法

 

3. 双向旋转(先左后右): 在节点A的左子树的右子树上插入新节点, 引起A的平衡因子由1变为2所要进行的旋转, 这时,需要两次旋转, 先左后右, 如下图:

平衡树构造算法平衡树构造算法

4.又向旋转(先右后左): 在节点A的右子树的左子树上插入新节点, 导致节点A的平衡因子由-1变为-2而进行旋转,先右旋转再左旋转:

平衡树构造算法平衡树构造算法

 

经过这两种变换, 就能达到新节点插入后, 保证树是一个平衡树.

 

简单代码实现(采用递归算法):

#define LeftHigh = 1

#define EqualHigh = 0

#define RightHigh = -1

struct AVLTreeNode

   int Key; // 节点键值

   int balanceFactor; //平衡因子

   AVLTreeNode lchild, //左孩子

   rchild, // 右孩子

   parent, // 父节点

   equal; // 相等节点,在树中有可能出现相同键值的节点, 则通过此指针把它们连接在一起.

}

int InsertAVLTreeNode(AVLTreeNode &ANode,&AParentNode, ANewNode; Boolean&AIsTaller)

{

  if (ANode == null) // t节点为空,则表示插入新节点NewNodeValue, 树将长高

  {

    // 插入新节点,父节点为AParnetNode, 返回为新的节点值

    ANode =ANewNode; // 直接设置节点关系

   ANode.parent = AParentNode;

   ANode.lchild = ANode.rchild = null;

   ANode.balanceFactor = 0; // 新加节点平衡因子为0

    AIsTaller= True; // 树长高了, 需要平衡处理

    Returntrue; // 返回真, 插入新节点

  

  if (ANewNode.Key = ANode.Key) {

    AIsTaller= False; // 树不需要增高

   ANode.equal = InserEqualNode(ANewNode, ANode); // 插入相等节点

    returnfalse; // 插入过程结束

  }

  if(ANewNode.Key < ANode.Key){// 在左子树上插入

   if(!InsertAVLTreeNode(ANode->lchild, ANode,ANewNode, AIsTaller)) return False; //没有插入或插入了相等节点

    if(AIsTaller){ // 树增高了

     if(ANode->balanceFactor = 1){ // 左子树高

       LeftBalance(ANode); // 左子树旋转

       AIsTaller := False;

     }

      elseif (ANode->balanceFactor=0){ANode.balanceFactor = 1;AIsTaller = True;}

     else if(ANode->balanceFactor=-1){ANode.balanceFactor= 0;AIsTaller = false;}

    }

  }

  else if (ANewNode.Key >ANode.Key)

  {

   if(!InsertAVLTreeNode(ANode->rchild, ANode,ANewNode, AIsTaller)) return false; // 没有插入任何节点或插入节点为相等节点

   if(AIsTaller){ // 树增高了

     if(ANode->balanceFactor =1){ANode->balanceFactor=0; AIsTaller = False;}

     else if(ANode->balanceFactor =0){ANode->balanceFactor = -1; AIsTaller = True;}

     else{ RightBalance(ANode), AIsTaller = False}

    }

  }

return true; // 插入节点成功, 如果有失败, 则在中途退出了.

}

 

void LeftBalance(AVLTreeNode &ANode)

{

  // 对以ANode为根的树左侧进行平衡处理

  lchild = ANode->lchild; //lchild 指向ANode的左子树的根节点;

 switch(lchild->balanceFactor){

    onLeftHigh: // 单向右旋转

     ANode->balanceFactor = EqualHigh;

     lchild->balanceFactor = EqualHigh;

      R_Rotate(ANode);break;

    onRightHigh: // 先左旋转再右旋转

     lrchild = lchild->rchild; // 左子树中的右子树节点;

     switch(lrchild->balanceFactor){

       on LeftHigh:

         ANode->balanceFactor= RightHigh;

         lchild->balanceFactor :=EqualHigh;      

         break;

       on EqualHigh: ANode->balancefactor =lchild->BalanceFactor = EqualHigh; break;

       onRightHig: ANode->balanceFactor = EqualHigh;lchild->balanceFactor = LeftHigh; break;

     }

     lrchild->balanceFactor = EqualHigh;

     // 进行旋转

    L_Rotate(lchild); R_Rotate(ANode);

  }

}

void RightBalance(AVLTreeNode ANode){

  rchild = ANode->rchild; //右子树的根节点;

  switch(rchild-balanceFactor){

    on LeftHigh: // 先右旋转再左旋转

       rlchild= rchild->lchild; // 右子树的左子树节点

      switch(rlchild-balanceFactor){

        on LeftHigh: ANode->balanceFactor = 0;rchild->balanceFactor = RightHigh; break;

        on EqualHigh: rchild-balanceFactor =ANode->balanceFactor = EqualHigh; break;

        on RightHigh: ANode->balanceFactor = LeftHigh;rchild-balanceFactor = EqualHigh;

      }

      rlchild->balanceFactor = EqualHigh;

       R_Rotate(rchild) ;L_Rotate(ANode);

      break;

    on RightHigh: // 单向左旋转

      rchild->balanceFactor =ANode->balanceFactor = EqualHigh;

      L_Rotate(ANode);

  }

}

 

// 左旋转

void L_Rotate(AVLTreeNode &ANode){

  rchild = ANode-rchild;

  ANode->lchild =rchild->lchild;

  rchild->lchild = ANode;

  ANode = rchild;

}

// 右旋转操作

void R_Rotate(AVLTreeNode &ANode){

  lchild = ANode->lchild;

  ANode->rchild =lchild->rchild;

  lchild->rchild = ANode;

  ANode = lchild;

}

 

 

// 平衡树搜索函数:

ANode BinaryTreeSearch(AVLTreeNode * ANode; const intAValue){

  if (ANode = null)

    returnnull;

  if (ANode.key == AValue)

   return ANode;

  if(Avalue< ANode.key)

    retrunBinaryTreeSearch(ANode->lchild, Avalue);

  else

    returnBinaryTreeSearch(ANode->rchild, Avalue);

}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:11751次
    • 积分:348
    • 等级:
    • 排名:千里之外
    • 原创:13篇
    • 转载:4篇
    • 译文:3篇
    • 评论:2条
    更好的了解我
    文章存档
    最新评论