平衡树构造算法

转载 2012年03月23日 21:21:03

构造平衡树算法:

  我们知道, 二叉搜索树的平均效率是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);

}


平衡树算法

  • 2014年08月27日 10:45
  • 4KB
  • 下载

查找算法及二叉平衡树

查找的分类: 1.静态查找 2.动态查找 3.哈希查找1.1顺序查找法//应用范围:顺序表或线性链表表示的表,表内元素之间无序。 // 在数组arr中查找等于k的元素,若找到,则函数返回该元素的...

数据结构与算法之AVL平衡树<六>

AVL平衡树

二叉平衡树的算法复杂度笔记

插入,删除 树的各种操作的复杂度都依赖于树的高度 所以普通的二叉查找树, 操作复杂度均为log(n),最坏情况可能O(n),可以证明,随机构造的树的平均高度为log(n),所以平均复杂度为log(n)...

二叉排序树、二叉平衡树算法

1.binary search tree,中文翻译为二叉搜索树、二叉查找树或者二叉排序树。简称为BST 2. 查找算法     这个比较简单,要么找到了,要么向左,要么向右。  BS...

编程算法 - 判断二叉树是不是平衡树 代码(C)

判断二叉树是不平衡树 代码(C)本文地址: http://blog.csdn.net/caroline_wendy题目: 输入一颗二叉树的根结点, 判断该树是不是平衡二叉树.二叉平衡树: 任意结点的左...

算法导论第十三章习题13-3——AVL树(高度平衡树)C++代码详细实现

AVL树是一种高度平衡树,对于每一个节点,其左子树的高度与右子树的高度相差之多为1。 AVL树是比红黑树更加平衡的树(红黑树中左右子树高度之比小于2)。 AVL树除了平衡性较好外,与普通的二叉查找...

|算法讨论|平衡树 学习笔记

题目 [平衡树]BZOJ 2028:求大于x的最小值,set可以过 [平衡树]BZOJ 3224:Treap、Splay实现名次树模板及讲解平衡树:Treap,Splay,SetTreap,Spl...
  • Darost
  • Darost
  • 2017年02月04日 13:01
  • 114

算法基础篇(11)------平衡树

能够表达一定元素顺序的二叉树叫二叉搜索树。二叉搜索树通常能在O(logN)的时间复杂度下查找某些节点的元素值,但是其容易退化成一条链导致时间复杂度变成O(N)。为解决这个问题,平衡树就诞生了。那么平衡...

平衡树 算法摘记

平衡树是计算机科学中的一类改进的二叉查找树。一般的二叉查找树的查询复杂度是跟目标结点到树根的距离(即深度)有关,因此当结点的深度普遍较大时,查询的均摊复杂度会上升,为了更高效的查询,平衡树应运而生了。...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:平衡树构造算法
举报原因:
原因补充:

(最多只允许输入30个字)