• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

Vigil

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

MOOC数据结构PTA-04-树5 Root of AVL Tree

题目

An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Figures 1-4 illustrate the rotation rules.
image
image
image
image
Now given a sequence of insertions, you are supposed to tell the root of the resulting AVL tree.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (≤20) which is the total number of keys to be inserted. Then N distinct integer keys are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the root of the resulting AVL tree in one line.

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 树是一种自平衡二叉搜索树。在AVL树中,任何节点的两个子子树的高度最多相差1;如果在任何时候它们相差超过 1,则进行重新平衡以恢复此属性。图 1-4 说明了轮换规则。
思路:随着插入随着判断是否需要调整旋转。

代码

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
    int data;
    struct node *lchild, *rchild;
    int height;
} Node, *Tree;

//函数声明
Tree BuildTree(int N);          //根据输入建立树
Tree Insert(Tree T, int data);  //在树中插入新节点
Tree NewNode(int data);         //新建结点
int GetLevel(Tree T);           //获得本树层数
Tree LLrotation(Tree T);        // LL旋转
Tree LRrotation(Tree T);        // LR旋转
Tree RRrotation(Tree T);        // RR旋转
Tree RLrotation(Tree T);        // RL旋转

//主函数
int main() {
    int N;
    scanf("%d", &N);
    Tree T = BuildTree(N);
    printf("%d", T->data);
    return 0;
}

Tree BuildTree(int N) {
    int i, data;
    scanf("%d", &data);
    Tree T = NewNode(data);

    for (i = 1; i < N; i++) {
        scanf("%d", &data);
        T = Insert(T, data);
    }
    return T;
}
Tree NewNode(int data) {
    Tree T = (Tree)malloc(sizeof(Node));
    T->data = data;
    T->lchild = NULL;
    T->rchild = NULL;
    T->height = 0;
    return T;
}
Tree Insert(Tree T, int data) {
    if (T == NULL)
        T = NewNode(data);
    else {
        if (data < T->data) {
            /*插入左子树*/
            T->lchild = Insert(T->lchild, data);
            /* 如果需要左旋 */
            if (GetLevel(T->lchild) - GetLevel(T->rchild) == 2)
                if (data < T->lchild->data)
                    T = LLrotation(T); /* 左单旋 */
                else
                    T = LRrotation(T); /* 左-右双旋 */
        }

        else if (data > T->data) {
            //插入右子树
            T->rchild = Insert(T->rchild, data);
            /* 如果需要右旋 */
            if (GetLevel(T->lchild) - GetLevel(T->rchild) == -2)
                if (data > T->rchild->data)
                    T = RRrotation(T); /* 右单旋 */
                else
                    T = RLrotation(T); /* 右-左双旋 */
        }
    }

    /* 别忘了更新树高 */
    int L = GetLevel(T->lchild);
    int R = GetLevel(T->rchild);
    T->height = L > R ? L + 1 : R + 1;
    return T;
}

int GetLevel(Tree T) {
    if (T) {
        int l = GetLevel(T->lchild);
        int r = GetLevel(T->rchild);
        return l > r ? l + 1 : r + 1;
    } else
        return 0;
}

Tree LLrotation(Tree T) {
    //右单旋转,需保障有左孩子
    Tree root = T->lchild;
    T->lchild = root->rchild;
    root->rchild = T;
    int TL = GetLevel(T->lchild);
    int TR = GetLevel(T->rchild);
    T->height = TL >= TR ? TL + 1 : TR + 1;

    int RL = GetLevel(root->lchild);
    int RR = GetLevel(root->rchild);
    root->height = RL >= RR ? RL + 1 : RR + 1;

    return root;
}
Tree RRrotation(Tree T) {
    //需保障T有右孩子
    Tree root = T->rchild;
    T->rchild = root->lchild;
    root->lchild = T;
    int TL = GetLevel(T->lchild);
    int TR = GetLevel(T->rchild);
    T->height = TL >= TR ? TL : TR;

    int RL = GetLevel(root->lchild);
    int RR = GetLevel(root->rchild);
    root->height = RL >= RR ? RL : RR;

    return root;
}
Tree LRrotation(Tree T) {
    /* T必须有一个左子结点B,且B必须有一个右子结点C
           将T、B与C做两次单旋,返回新的根结点C */

    /* 将B与C做RR旋转,C被返回 */
    T->lchild = RRrotation(T->lchild);
    /* 将T与C做左单旋,C被返回 */
    return LLrotation(T);
}
Tree RLrotation(Tree T) {
    /* T必须有一个右子结点B,且B必须有一个左子结点C
        将T、B与C做两次单旋,返回新的根结点C */

    /* 将B与C做LL旋转,C被返回 */
    T->rchild = LLrotation(T->rchild);
    /* 将T与C做左单旋,C被返回 */
    return RRrotation(T);
}

posted on 2021-08-11 22:31  VigilYang  阅读(77)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3