支持HW团队,就支付宝领取下面的红包吧!(2018年3月31前,就几毛,也会几块,可以和其他红包叠加使用),你领取消费,HW有奖励。红包使用无条件限制,有条件请注意是不是有病毒。

小伙伴们,给大家发红包喽!人人可领,领完就能用。祝大家领取的红包金额大大大!#吱口令#长按复制此消息,打开支付宝就能领取!er1OEj73Uj

登入 注册 | 验证
| 搜索
HelloWorld论坛 : > 计算机科学、技术、教学> 编程专题> 开源免费项目> [转]平衡二叉树
 
 
 
 
类别:算法 阅读:3627 评论:0 时间:五月 21, 2013, 10:08 a.m. 关键字:AVL tree

 

来源:http://www.cppblog.com/bellgrade/archive/2009/10/12/98402.html
http://blog.csdn.net/w170532934/article/details/7571281
收集两篇文章
形态匀称的二叉树称为平衡二叉树 (Balanced binary tree) ,其严格定义是:
  一棵空树是平衡二叉树;若 T 是一棵非空二叉树,其左、右子树为 TL 和 TR ,令 hl 和 hr 分别为左、右子树的深度。当且仅当
   ①TL 、 TR 都是平衡二叉树; 
   ② | hl - hr |≤ 1;
时,则 T 是平衡二叉树。
【例】如图 8.4 所示。
         
             (a)平衡二叉树           (b)非平衡二叉树
                      图8.3 平衡二叉树与非平衡二叉树
相应地定义 hl - hr 为二叉平衡树的平衡因子 (balance factor) 。因此,平衡二叉树上所有结点的平衡因子可能是 -1 , 0 , 1 。换言之,若一棵二叉树上任一结点的平衡因子的绝对值都不大于 1 ,则该树是就平衡二叉树。
动态平衡技术 
1.动态平衡技术
Adelson-Velskii 和 Landis 提出了一个动态地保持二叉排序树平衡的方法,其基本思想是:
  在构造二叉排序树的过程中,每当插入一个结点时,首先检查是否因插入而破坏了树的平衡性,如果是因插入结点而破坏了树的平衡性,则找出其中最小不平衡子树,在保持排序树特性的前提下,调整最小不平衡子树中各结点之间的连接关系,以达到新的平衡。通常将这样得到的平衡二叉排序树简称为 AVL 树
2.最小不平衡子树
  以离插入结点最近、且平衡因子绝对值大于 1 的结点作根结点的子树。为了简化讨论,不妨假设二叉排序树的最小不平衡子树的根结点为 A ,则调整该子树的规律可归纳为下列四种情况:
(1) LL 型:
  新结点 X 插在 A 的左孩子的左子树里。调整方法见图 8.5(a) 。图中以 B 为轴心,将 A 结点从 B 的右上方转到 B 的右下侧,使 A 成为 B 的右孩子。
      
          图8.5 平衡调整的4种基本类型(结点旁的数字是平衡因子)
(2)RR 型:
  新结点 X 插在 A 的右孩子的右子树里。调整方法见图 8.5(b) 。图中以 B 为轴心,将 A 结点从 B 的左上方转到 B 的左下侧,使 A 成为 B 的左孩子。
(3)LR 型:
  新结点 X 插在 A 的左孩子的右子树里。调整方法见图 8.5(c) 。分为两步进行:第一步以 X 为轴心,将 B 从 X 的左上方转到 X 的左下侧,使 B 成为 X 的左孩子, X 成为 A 的左孩子。第二步跟 LL 型一样处理 ( 应以 X 为轴心 ) 。 
(4)RL 型:
  新结点 X 插在 A 的右孩子的左子树里。调整方法见图 8.5(d) 。分为两步进行:第一步以 X 为轴心,将 B 从 X 的右上方转到 X 的右下侧,使 B 成为 X 的右孩子, X 成为 A 的右孩子。第二步跟 RR 型一样处理 ( 应以 X 为轴心 ) 。
【例】
实际的插入情况,可能比图 8.5 要复杂。因为 A 、 B 结点可能还会有子树。现举一例说明,设一组记录的关键字按以下次序进行插入: 4 、 5 、 7 , 2 、 1 、 3 、 6 ,其生成及调整成二叉平衡树的过程示于图 8.6 。 
  在图 8.6 中,当插入关键字为 3 的结点后,由于离结点 3 最近的平衡因子为 2 的祖先是根结点 5 。所以,第一次旋转应以结点 4 为轴心,把结点 2 从结点 4 的左上方转到左下侧,从而结点 5 的左孩子是结点 4 ,结点 4 的左孩子是结点 2 ,原结点 4 的左孩子变成了结点 2 的右孩子。第二步再以结点 4 为轴心,按 LL 类型进行转换。这种插入与调整平衡的方法可以编成算法和程序,这里就不再讨论了。 

         图 8.6 二叉平衡树插入结点 ( 结点旁的数字为其平衡因子 ) 

平衡二叉树多用于查找数据,所以平衡二叉树又是颗二叉排序树。

那么如何创建一颗平衡二叉树呢?

创建平衡二叉树,我们采用依次插入节点的方式进行。而平衡二叉树上插入节点采用递归的方式进行。递归算法如下:

(1) 若该树为一空树,那么插入一个数据元素为e的新节点作为平衡二叉树的根节点,树的高度增加1。

(2) 若待插入的数据元素e和平衡二叉树(BBST)的根节点的关键字相等,那么就不需要进行插入操作。

(3) 若待插入的元素e比平衡二叉树(BBST)的根节点的关键字小,而且在BBST的左子树中也不存在和e有相同关键字的节点,则将e插入在BBST的左子树上,并且当插入之后的左子树深度增加1时,分别就下列情况处理之。

(a) BBST的根节点的平衡因子为-1(右子树的深度大于左子树的深度):则将根节点的平衡因子更改为0,BBST的深度不变;

(b) BBST的根节点的平衡因子为0(左右子树的深度相等):则将根节点的平衡因子修改为1,BBST的深度增加1;

(c) BBST的根节点的平衡因子为1(左子树的深度大于右子树的深度):若BBST的左子树根节点的平衡因子为1,则需要进行单向右旋转平衡处理,并且在右旋处理后,将根节点和其右子树根节点的平衡因子更改为0,树的深度不变;

若BBST的左子树根节点的平衡因子为-1,则需进行先向左,后向右的双向旋转平衡处理,并且在旋转处理之后,修改根节点和其左,右子树根节点的平衡因子,树的深度不变;

(4) 若e的关键字大于BBST的根节点的关键字,而且在BBST的右子树中不存在和e有相同关键字的节点,则将e插入到BBST的右子树上,并且当插入之后的右子树深度加1时,分别就不同的情况处理之。

(a) BBST的根节点的平衡因子是1(左子树的深度大于右子树的深度):则将根节点的平衡因子修改为0,BBST的深度不变;

(b) BBST的根节点的平衡因子是0(左右子树的深度相等):则将根节点的平衡因子修改为-1,树的深度加1;

(c) BBST的根节点的平衡因子为-1(右子树的深度大于左子树的深度):若BBST的右子树根节点的平衡因子为1,则需要进行两次选择,第一次先向右旋转,再向左旋转处理,并且在旋转处理之后,修改根节点和其左,右子树根节点的平衡因子,树的深度不变;

若BBST的右子树根节点的平衡因子为1,则需要进行一次向左的旋转处理,并且在左旋之后,更新根节点和其左,右子树根节点的平衡因子,树的深度不变;


下面附上本人的代码:

#include <stdio.h> 
#include <stdlib.h> 
/************************************************************************/ 
/* 平衡二叉树---AVL */ 
/************************************************************************/ 
#define LH +1 
#define EH 0 
#define RH -1 
typedef int ElemType; 
typedef struct BSTNode{ 
        ElemType data; 
        int bf;//balance flag 
        struct BSTNode *lchild,*rchild; 
}*PBSTree; 

void R_Rotate(PBSTree* p) 
{ 
        PBSTree lc = (*p)->lchild; 
        (*p)->lchild = lc->rchild; 
        lc->rchild = *p; 
        *p = lc; 
} 

void L_Rotate(PBSTree* p) 
{ 
        PBSTree rc = (*p)->rchild; 
        (*p)->rchild = rc->lchild; 
        rc->lchild = *p; 
        *p = rc; 
} 

void LeftBalance(PBSTree* T) 
{ 
        PBSTree lc,rd; 
        lc = (*T)->lchild; 
        switch (lc->bf) 
        { 
        case LH: 
                (*T)->bf = lc->bf = EH; 
                R_Rotate(T); 
                break; 
        case RH: 
                rd = lc->rchild; 
                switch(rd->bf) 
                { 
                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 = EH; 
                L_Rotate(&(*T)->lchild); 
                R_Rotate(T); 
                break; 
        } 
} 

void RightBalance(PBSTree* T) 
{ 
        PBSTree lc,rd; 
        lc= (*T)->rchild; 
        switch (lc->bf) 
        { 
        case RH: 
                (*T)->bf = lc->bf = EH; 
                L_Rotate(T); 
                break; 
        case LH: 
                rd = lc->lchild; 
                switch(rd->bf) 
                { 
                case LH: 
                        (*T)->bf = EH; 
                        lc->bf = RH; 
                        break; 
                case EH: 
                        (*T)->bf = lc->bf = EH; 
                        break; 
                case RH: 
                        (*T)->bf = EH; 
                        lc->bf = LH; 
                        break; 
                } 
                rd->bf = EH; 
                R_Rotate(&(*T)->rchild); 
                L_Rotate(T); 
                break; 
        } 
} 

int InsertAVL(PBSTree* T,ElemType e,bool* taller) 
{ 
        if ((*T)==NULL) 
        { 
                (*T)=(PBSTree)malloc(sizeof(BSTNode)); 
                (*T)->bf = EH; 
                (*T)->data = e; 
                (*T)->lchild = NULL; 
                (*T)->rchild = NULL; 
        } 
        else if (e == (*T)->data) 
        { 
                *taller = false; 
                return 0; 
        } 
        else if (e < (*T)->data) 
        { 
                if(!InsertAVL(&(*T)->lchild,e,taller)) 
                        return 0; 
                if(*taller) 
                { 
                        switch ((*T)->bf) 
                        { 
                        case LH: 
                                LeftBalance(T); 
                                *taller = false; 
                                break; 
                        case EH: 
                                (*T)->bf = LH; 
                                *taller = true; 
                                break; 
                        case RH: 
                                (*T)->bf = EH; 
                                *taller = false; 
                                break; 
                        } 
                } 
        } 
        else 
        { 
                if(!InsertAVL(&(*T)->rchild,e,taller)) 
                        return 0; 
                if (*taller) 
                { 
                        switch ((*T)->bf) 
                        { 
                        case LH: 
                                (*T)->bf = EH; 
                                *taller = false; 
                                break; 
                        case EH: 
                                (*T)->bf = RH; 
                                *taller = true; 
                                break; 
                        case RH: 
                                RightBalance(T); 
                                *taller = false; 
                                break; 
                        } 
                } 
        } 
        return 1; 
} 

bool FindNode(PBSTree root,ElemType e,PBSTree* pos) 
{ 
        PBSTree pt = root; 
        (*pos) = NULL; 
        while(pt) 
        { 
                if (pt->data == e) 
                { 
                        //找到节点,pos指向该节点并返回true 
                        (*pos) = pt; 
                        return true; 
                } 
                else if (pt->data>e) 
                { 
                        pt = pt->lchild; 
                } 
                else 
                        pt = pt->rchild; 
        } 
        return false; 
} 
void InorderTra(PBSTree root) 
{ 
        if(root->lchild) 
                InorderTra(root->lchild); 
        printf("%d ",root->data); 
        if(root->rchild) 
                InorderTra(root->rchild); 
} 

int main() 
{ 
        int i,nArr[] = {1,23,45,34,98,9,4,35,23}; 
        PBSTree root=NULL,pos; 
        bool taller; 
        for (i=0;i<9;i++) 
        { 
                InsertAVL(&root,nArr[i],&taller); 
        } 
        InorderTra(root); 
        if(FindNode(root,103,&pos)) 
                printf("\n%d\n",pos->data); 
        else 
                printf("\nNot find this Node\n"); 
        return 0; 
}


 

相关博文:
[挂载人]初学MPEG [审核人]初学MPEG 推荐

个人签名--------------------------------------------------------------------------------

Please Login (or Sign Up) to leave a comment