PAT_甲级_1066 Root of AVL Tree (25point(s)) (C++)【AVL树构建过程图解】

目录

1,题目描述

 题目大意

2,思路

AVL树

不平衡的类型

 插入节点

3,AC代码


1,题目描述

Sample Input 1:

5
88 70 61 96 120

 

Sample Output 1:

70

 

Sample Input 2:

7
88 70 61 96 120 90 65

 

Sample Output 2:

88

 题目大意

给出一个序列,输出按照此序列构造的AVL树的根节点的值。

 

2,思路

题目意思很直接,就是赤裸裸地构造AVL树。

AVL树

平衡二叉树(Balance Binary Tree),又称AVL树,是一棵二叉排序树,或者为空,或者满足以下条件:

  1. 左、右子树高度差的绝对值不大于1;
  2. 左、右子树都是平衡二叉树。

平衡二叉树可以确保平均查找长度较小。

不平衡的类型

根据新插入结点最低不平衡结点的位置关系分为LL型、RR型、LR型和RL型4种类型分别处理:

(注:A为最底不平衡点;方框表示子树;灰色方框为新插入的节点;节点的调整顺序很重要)

LL型

①B的右子树调为A的左子树,即:A->lChild=B->rChild;

② A调为B的右孩子,即:B->rChild=A;

③ B成为调整后的子树根结点。

RR型

① B的左子树调为A的右子树,即: A->rChild=B->lChild;

② A调为B的左孩子,即: B->lChild=A;

③ B成为调整后的子树根结点。

LR型

① C的左子树调为B的右子树,即:B->rChild=C->lChild;      

     C的右子树调为A的左子树,即:A->lChild=C->rChild;

② B调为C的左子树,即:C->lChild=B;      

     A调为C的右子树,即:C->rChild=A;

③ C成为调整后的子树根结点;

RL型

① C的左子树调为A的右子树,即:A->rChild=C->lChild;      

     C的右子树调为B的左子树,即:B->lChild=C->rChild;

② A调为C的左孩子,即:C->lChild=A;    

    B调为C的右孩子,即:C->rChild=B;

③ C成为调整后的子树根结点。

 

 插入节点

设计函数:

int getHeight(node *root):获得当前节点的高度;

node *insert(node *root, int val):插入值为val的节点;

(递归过程的理解:在最低处的节点插入数据后,函数返回,检查节点的父节点平衡是否被破坏,若被破坏,则进行调整;将其父节点替换为当前节点,继续递归。。。)

int getHeight(node *root){
    if(root == NULL) return 0;
    return max(getHeight(root->left), getHeight(root->right)) + 1;
}
node *insert(node *root, int val){
    if(root == NULL){
        root = new node();
        root->value = val;
        root->left = root->right = NULL;
    }
    else if(val < root->value){
        root->left = insert(root->left, val);
        //插入节点后需要判断当前节点的平衡是否被破坏
        if(getHeight(root->left) - getHeight(root->right) == 2){//root最低不平衡节点
            root = val < root->left->value ? rotateLL(root) : rotateLR(root);
        }
    }
    else{
        root->right = insert(root->right, val);
        if(getHeight(root->left) - getHeight(root->right) == -2){//root最低不平衡节点
            root = val > root->right->value ? rotateRR(root) : rotateRL(root);
        }
    }
    return root;//最终的根节点
}

3,AC代码

#include<bits/stdc++.h>
using namespace std;

struct node{
    int value;
    struct node *left, *right;
};
node *rotateLL(node *root){
    node *t = root->left;
    root->left = t->right;
    t->right = root;
    return t;
}
node *rotateRR(node *root){
    node *t = root->right;
    root->right = t->left;
    t->left = root;
    return t;
}
node *rotateLR(node *root){
    node *A = root, *B = root->left, *C = root->left->right;
    B->right = C->left;
    A->left = C->right;
    C->left = B;C->right = A;
    return C;
}
node *rotateRL(node *root){
    node *A = root, *B = root->right, *C = root->right->left;
    A->right = C->left;
    B->left = C->right;
    C->left = A;C->right = B;
    return C;
}
int getHeight(node *root){
    if(root == NULL) return 0;
    return max(getHeight(root->left), getHeight(root->right)) + 1;
}
node *insert(node *root, int val){
    if(root == NULL){
        root = new node();
        root->value = val;
        root->left = root->right = NULL;
    }
    else if(val < root->value){
        root->left = insert(root->left, val);
        if(getHeight(root->left) - getHeight(root->right) == 2){//root最低不平衡节点
            //root = val < root->left->value ? rotateLL(root) : rotateLR(root);
            if(val < root->left->value)
                root = rotateLL(root);//LL型 需向右旋转
            else
                root = rotateLR(root);
        }
    }
    else{
        root->right = insert(root->right, val);
        if(getHeight(root->left) - getHeight(root->right) == -2){//root最低不平衡节点
            root = val > root->right->value ? rotateRR(root) : rotateRL(root);
        }
    }
    return root;//最终的根节点
}
int main(){
#ifdef ONLINE_JUDGE
#else
    freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE

    int N, val;
    node *AVLTree = NULL;
    scanf("%d", &N);
    for(int i = 0; i < N; i++){
        scanf("%d", &val);
        AVLTree = insert(AVLTree, val);
    }
    printf("%d", AVLTree->value);
    return 0;
}

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值