浙大数据结构第四周之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.

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

简单翻译:

就是给一个二叉平衡树的插入序列,依据这个序列构建二叉平衡树,并返回根节点

主要思路:

用插入法构建,即需要在程序里实现左右单旋与左右双旋

要特别注意的是,如果插入一个节点导致树不平衡了,我们要找到从下往上第一个不平衡的地方进行调整,调整完整个树就平衡了,而不是说要返回到最上面进行调整。

举个列子

假设我们在递归的过程中,输入AVLTree是NULL,也就是如下情况:

15这里是一定平衡的(左右都是空),返回给11,11这里肯定也是平衡的,返回给9,但9就不是平衡的了

然后就可以判断让9恢复平衡应该进行哪种操作,即RR还是RL,这里判断为RR。

调整完以后,再返回到9的父节点,这个时候9的父节点再进行判断,以此类推。

第一次写错误:

(1)对树的高度的把握,准确求出树高是旋转的关键,本题实现是直接存储在树节点中,通过直接访问节点与计算左右子树高度最大值再加1求得当前节点高度

在每次旋转后都需要求出两个"交换位置"节点的各自树高

插入操作最后再求当前节点树高

(2)

左旋:根节点与左孩子"交换"位置,左孩子右子树挂到根节点左子树

右旋:根节点与右孩子"交换"位置,右孩子左子树挂到根节点右子树

左-右双旋:先根节点左孩子与它的右孩子右旋,再根节点与现在的左孩子左旋

右-左双旋:先根节点右孩子与它的左节点左旋,再根节点与现在的右孩子右旋

代码实现:

/*
定义树的数据结构,其中每个节点保存以当前节点为root的子树高度
读入数据
插入节点以建树
左旋(1)左单旋(2)左-右双旋
右旋(1)右单旋(2)右-左双旋
*/
#include <stdio.h>
#include <stdlib.h>
/*定义树的数据结构*/
typedef struct TreeNode TreeNode;
typedef TreeNode* Position;
typedef Position AVLTree;
struct TreeNode {
    int Data;
    Position Leftchild;
    Position Rightchild;
    int Height;
};
/*获取树的高度*/
int Max(int a, int b) {
    return a > b ? a : b;
}
int GetTreeHeight(Position root) { 
    if(root == NULL) {
        return 0;
    }
    else return root->Height;
}
/*每次旋转后都要重新获取以当前节点为根节点的子树高度*/
/*左单旋*/
Position SingleLeftRotation(Position root) {
    Position initialRoot = root;
    Position newRoot = root->Leftchild;
    root->Leftchild = root->Leftchild->Rightchild;
    newRoot->Rightchild = initialRoot;
    newRoot->Height = Max(GetTreeHeight(newRoot->Leftchild), GetTreeHeight(newRoot->Rightchild)) + 1;
    initialRoot->Height = Max(GetTreeHeight(initialRoot->Leftchild), GetTreeHeight(initialRoot->Rightchild)) + 1;
    return newRoot;
}
/*右单旋*/
Position SingleRightRotation(Position root) {
    Position initialRoot = root;
    Position newRoot = root->Rightchild;
    root->Rightchild = root->Rightchild->Leftchild;
    newRoot->Leftchild = initialRoot;
    initialRoot->Height = Max(GetTreeHeight(initialRoot->Leftchild), GetTreeHeight(initialRoot->Rightchild)) + 1;
    newRoot->Height = Max(GetTreeHeight(newRoot->Leftchild), GetTreeHeight(newRoot->Rightchild)) + 1;
    return newRoot;
}
/*左-右双旋*/
Position DoubleLeftRightRotation(Position root) {
    root->Leftchild = SingleRightRotation(root->Leftchild);
    return SingleLeftRotation(root);
}
/*右-左双旋*/
Position DoubleRightLeftRotation(Position root) {
    root->Rightchild = SingleLeftRotation(root->Rightchild);
    return SingleRightRotation(root);
}
/*插入节点*/
Position Insert(Position root, int data) {
    if(root == NULL) {
        root = (Position)malloc(sizeof(TreeNode));
        root->Data = data;
        root->Leftchild = root->Rightchild = NULL;
        root->Height = 1;
        return root;
    }

    if(root->Data > data) {
        root->Leftchild = Insert(root->Leftchild, data);
        if(GetTreeHeight(root->Leftchild) - GetTreeHeight(root->Rightchild) > 1) {
            if(root->Leftchild->Data > data) {  //左单旋
                root = SingleLeftRotation(root);
            }
            else {  //左-右双旋
                root = DoubleLeftRightRotation(root);
            }
        }
    }   
    else if(root->Data < data) {
        root->Rightchild = Insert(root->Rightchild, data);
        if(GetTreeHeight(root->Rightchild) - GetTreeHeight(root->Leftchild) > 1) {
            if(root->Rightchild->Data < data) {
                root = SingleRightRotation(root);
            }
            else {
                root = DoubleRightLeftRotation(root);
            }
        }
    }

    root->Height = Max(GetTreeHeight(root->Leftchild), GetTreeHeight(root->Rightchild)) + 1;

    return root;
}

void DeleteTree(AVLTree root) {
    if(root == NULL) {
        return;
    }

    DeleteTree(root->Leftchild);
    DeleteTree(root->Rightchild);
    free(root);
    return;
}

/*建树*/
int BuildTree() {
    int N;
    scanf("%d", &N);
    AVLTree root = NULL;
    for(int i = 0; i < N; i++) {
        int data;
        scanf("%d", &data);
        root = Insert(root, data);
    }
    int ret = root->Data;
    DeleteTree(root);
    return ret;
}

int main() {
    int root = BuildTree();
    printf("%d", root);
    return 0;
}

参考文章

相关推荐
Heisenberg~5 分钟前
详解八大排序(五)------(计数排序,时间复杂度)
c语言·数据结构·排序算法
Hera_Yc.H11 小时前
数据结构之一:复杂度
数据结构
肥猪猪爸12 小时前
使用卡尔曼滤波器估计pybullet中的机器人位置
数据结构·人工智能·python·算法·机器人·卡尔曼滤波·pybullet
linux_carlos12 小时前
环形缓冲区
数据结构
readmancynn12 小时前
二分基本实现
数据结构·算法
Bucai_不才13 小时前
【数据结构】树——链式存储二叉树的基础
数据结构·二叉树
盼海13 小时前
排序算法(四)--快速排序
数据结构·算法·排序算法
一直学习永不止步13 小时前
LeetCode题练习与总结:最长回文串--409
java·数据结构·算法·leetcode·字符串·贪心·哈希表
珹洺14 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode
几窗花鸢14 小时前
力扣面试经典 150(下)
数据结构·c++·算法·leetcode