平衡二叉树

平衡二叉树

平衡二叉树分为三部分:创建AVL树节点、将结点插入到AVL树中、组装

typedef struct AVLTreeNode{
    /* data */
    int key; //键值
    int height;
    struct AVLTreeNode *left; //左孩子
    struct AVLTreeNode *right; //右孩子
}Node,*AVLTree;

int Height(AVLTree p){return (p==NULL) ? -1:p->height;}
int MAX(int a,int b){return a>b?a:b;}
void postorder_avltree(AVLTree p){ /*后序遍历AVL树*/}

创建AVL树

创建根节点

/*创建AVL树结点*/
static Node* avltree_creat_node(int key,Node *left,Node *right){
    Node* p;
    if((p=(Node*)malloc(sizeof(Node)))==NULL) return NULL;//申请空间并判定是否申请成功
    p->key=key;//key=key
    p->height=0;//高度等于0
    p->left=left;
    p->right=right;
    return p;
}

将结点插入到AVL树中

两点:判断不平衡的条件以及相对应的插入方法

判断条件

/*将结点插入到AVL树中并返回根结点*/
Node* avltree_insert(AVLTree tree, int key){
    if(tree==NULL){//只有这段代码是插入的代码
        tree=avltree_creat_node(key,NULL,NULL);
        if(tree==NULL) return NULL;
    }
    else if (key<tree->key){
        /* code */
        tree->left=avltree_insert(tree->left,key);
        if(Height(tree->left)-Height(tree->right)==2){//左子树高度减去右子树高度=2
            if(key<tree->left->key) tree=LL_Rotation(tree);//左-右=2&&引起失衡的因子比根节点的左子树的值小 LL旋转
            else tree=LR_Rotation(tree);//左-右=2&&引起失衡的因子比根节点的左子树的值大 LR旋转
        }
    }
    else if(key>tree->key){
        /* code */
        tree->right=avltree_insert(tree->right,key);
        if(Height(tree->right)-Height(tree->left)==2){//右子树高度减去左子树高度=2
            if(key<tree->left->key) tree=RR_Rotation(tree);//右-左=2&&引起失衡的因子比根节点的右子树的值大 RR旋转
            else tree=RL_Rotation(tree);//右-左=2&&引起失衡的因子比根节点的右子树的值小 RL旋转
        }
    }
    else{//key=tree.key 添加失败

    }
    tree->height=MAX(Height(tree->left),Height(tree->right))+1;
    return tree;//插入之后返回返回插入的结点本身
}

对应的情况

/*LL:左单旋转。 返回值:旋转后的根节点*/
static Node* LL_Rotation(AVLTree k2){
    AVLTree k1;//等于根节点的左子树变为了根节点
    k1=k2->left;//选取根节点的左子树为k1
    k2->left=k1->right;//k1的右子树变为k2的左子树
    k1->right=k2;//k2变为k1的右子树
    k2->height=MAX(Height(k2->left),Height(k2->right))+1;//界定k2的高度
    k1->height=MAX(Height(k1->left),k2->height)+1;//界定k1的高度
    return k1;//返回k1
}
/*RR:右单旋转。 返回值:旋转后的根{节点*/
static Node* RR_Rotation(AVLTree k1){
    AVLTree k2;//等于根节点的右子树变为了根节点
    k2=k1->right;//选取根节点的左子树为k2
    k1->right=k2->left;//k2的左子树变为k1的右子树
    k2->left=k1;//k1变为k2的左子树
    k1->height=MAX(Height(k2->left),Height(k2->right))+1;//界定k1的高度
    k2->height=MAX(Height(k1->left),k2->height)+1;//界定k2的高度
    return k2;//返回k2
}
/*LR:左双旋转。 返回值:旋转后的根节点*/
static Node* LR_Rotation(AVLTree k1){
    k1->left=RR_Rotation(k1->left);//调整左子树的RR旋转
    return LL_Rotation(k1);//调整根节点的LL旋转
}
/*RL:右双旋转。 返回值:旋转后的根节点*/
static Node* RL_Rotation(AVLTree k1){
    k1->right=LL_Rotation(k1->right);//调整右子树的LL旋转
    return RR_Rotation(k1);//调整根节点的RR旋转
}

组装

void main(){
    int arr[]={1,2,5,9,56,78,1};
    AVLTree root=NULL;//一个根节点
    for(int i=0;i<7;i++){//开始插入
        root=avltree_insert(root,arr[i]);
    }
    postorder_avltree(root);
}

LL顾名思义就是左子树的左边失衡了
RR右子树的右边失衡了
……

在进行LL RR LR RL操作的时候 要将其想象成
在这里插入图片描述
截图自这个文章
LL完全体
这个样子

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值