平衡二叉树

平衡二叉树

平衡二叉树简称平衡树,是由Adelson-Velskii和Landis于1962年首先提出的,所以又称为AVL树,平衡二叉树的性质如下:它的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值不超过1。

平衡因子BF=左子树的深度-右子树的深度,BF只能为-1,0,1。

平衡二叉树是对二叉搜索树(又称为二叉排序树)的一种改进。二叉搜索树有一个缺点就是,树的结构是无法预料的,随意性很大,它只与节点的值和插入的顺序有关系,往往得到的是一个不平衡的二叉树。在最坏的情况下,可能得到的是一个单支二叉树,其高度和节点数相同,相当于一个单链表,导致平均查找长度ASL很大,对其正常的时间复杂度有O(logn)变成了O(n),从而丧失了二叉排序树的一些应该有的优点。

假设我们已经有棵平衡二叉树,现在让我们来看看插入节点后,原来节点失去平衡后,我们进行选择的处理方式。

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

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

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

(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;  
}  


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值