PTA Root of AVL Tree (AVL树模板+四种旋转+指针)

关于AVL树(平衡二叉搜索树,高度为lgn)的讲解,双手呈上某大佬博客:https://www.cnblogs.com/zhuwbox/p/3636783.html

我从这题get到一个新的结构体写法(姿势):

typedef struct treeNode
{
    int val;
    treeNode *left;
    treeNode *right;
    int height;
}node, *tree;//node 是treeNode结构体,*tree是结构体指针

我对AVL树的理解:

按照插入节点时旋转的次数划分,可以分为两种旋转(单旋和双旋);继续划分,按照插入节点在根节点左右子树的不同,可以具体划分为四种旋转:单旋转:单左右旋(左左右旋),单右左旋(右右左旋);双旋转:左右左右旋,右左右左旋

例子(搬运于大佬博客):

代码:

tree rightRotation(tree t)//左左右旋
{
    tree l=t->left;
    t->left=l->right;
    l->right=t;
    t->height=max(height(t->left), height(t->right))+1;//跟新节点高度
    l->height=max(height(l->left), height(l->right))+1;
    return l;//l是新的根
}

tree leftRotation(tree t)//右右左旋
{
    tree l=t->right;
    t->right=l->left;
    l->left=t;
    t->height=max(height(t->left), height(t->right))+1;//跟新节点高度
    l->height=max(height(l->left), height(l->right))+1;
    return l;//l是新的根
}

tree leftRightRotation(tree t)//左右左右旋
{
    t->left=leftRotation(t->left);
    return rightRotation(t);
}

tree rightLeftRotation(tree t)//右左右左旋
{
    t->right=rightRotation(t->right);
    return leftRotation(t);
}

建树函数很简单,插入节点函数要特别提一下。如果t为NULL(树还没有根),那么初始化根节点;如果t非空且val>t->val,插入右节点;如果t非空且val<t->val,插入左节点。一旦高度差值为2,进行相应的AVL旋转(先插入节点再旋转),最后跟新t节点高度。代码:

tree treeCreate(tree t)
{
    int val;
    for(int i=1;i<=n;++i){
        cin>>val;
        t=nodeInsert(t, val);
    }
    return t;
}

tree nodeInsert(tree t, int val)
{
    if(!t) {t=new node;t->left=t->right=NULL;t->height=0;t->val=val;}
    else if(val>t->val) {//向节点右边插入值
        t->right=nodeInsert(t->right, val);//先插入后旋转
        if(height(t->right)-height(t->left)==2) {//只会出现右节点比左节点大2的情况
            if(val>t->right->val)
                t=leftRotation(t);//右右左旋
           else
                t=rightLeftRotation(t);//右左右左旋
        }
    }
    else if(val<t->val) {//向节点左边插入
        t->left=nodeInsert(t->left, val);
        if(height(t->left)-height(t->right)==2) {
            if(val<t->left->val)
                t=rightRotation(t);//左左右旋
            else
                t=leftRightRotation(t);//左右左右旋
        }
    }
    t->height=max(height(t->left), height(t->right))+1;//更新height
    return t;
}

main函数中定义树根t,注意将t设置为NULL,否则t作为野指针难以维护(我不会告诉你这是我调了靠近一个小时的bug)

{
    cin>>n;
    tree t=NULL;//先指定t指向NULL,否则t是野指针,非常难处理
    t=treeCreate(t);
    if(t) cout<<t->val<<endl;
    return 0;
}

全部代码:

#include <bits/stdc++.h>
using namespace std;
//AVL树的四种旋转情况:单旋转:左左右旋,右右左旋,左右左右旋,右左右左旋

int n;
typedef struct treeNode
{
    int val;
    treeNode *left;
    treeNode *right;
    int height;
}node, *tree;//node 是treeNode结构体,*tree是结构体指针

int height(tree t)//计算树的高度
{
    if(!t) return 0;//空树
    return t->height;
}

tree rightRotation(tree t)//左左右旋
{
    tree l=t->left;
    t->left=l->right;
    l->right=t;
    t->height=max(height(t->left), height(t->right))+1;//跟新节点高度
    l->height=max(height(l->left), height(l->right))+1;
    return l;//l是新的根
}

tree leftRotation(tree t)//右右左旋
{
    tree l=t->right;
    t->right=l->left;
    l->left=t;
    t->height=max(height(t->left), height(t->right))+1;//跟新节点高度
    l->height=max(height(l->left), height(l->right))+1;
    return l;//l是新的根
}

tree leftRightRotation(tree t)//左右左右旋
{
    t->left=leftRotation(t->left);
    return rightRotation(t);
}

tree rightLeftRotation(tree t)//右左右左旋
{
    t->right=rightRotation(t->right);
    return leftRotation(t);
}

tree nodeInsert(tree t, int val)
{
    if(!t) {t=new node;t->left=t->right=NULL;t->height=0;t->val=val;}
    else if(val>t->val) {//向节点右边插入值
        t->right=nodeInsert(t->right, val);//先插入后旋转
        if(height(t->right)-height(t->left)==2) {//只会出现右节点比左节点大2的情况
            if(val>t->right->val)
                t=leftRotation(t);//右右左旋
           else
                t=rightLeftRotation(t);//右左右左旋
        }
    }
    else if(val<t->val) {//向节点左边插入
        t->left=nodeInsert(t->left, val);
        if(height(t->left)-height(t->right)==2) {
            if(val<t->left->val)
                t=rightRotation(t);//左左右旋
            else
                t=leftRightRotation(t);//左右左右旋
        }
    }
    t->height=max(height(t->left), height(t->right))+1;//更新height
    return t;
}

tree treeCreate(tree t)
{
    int val;
    for(int i=1;i<=n;++i){
        cin>>val;
        t=nodeInsert(t, val);
    }
    return t;
}

void lrd(tree t)//后序遍历 输出调试
{
    if(t){
        lrd(t->left);
        lrd(t->right);
        cout<<t->val<<endl;
    }
}
int main()
{
    cin>>n;
    tree t=NULL;//先指定t指向NULL,否则t是野指针,非常难处理
    t=treeCreate(t);
    //lrd(t);
    if(t) cout<<t->val<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/ChenyangXu/p/10739516.html

时间: 2024-10-13 00:13:25

PTA Root of AVL Tree (AVL树模板+四种旋转+指针)的相关文章

Android 查看项目依赖树的四种方式

Android 查看项目依赖树的四种方式: 方式一: ./gradlew 模块名:dependencies //查看单独模块的依赖 ./gradlew :app:dependencies --configuration compile //查看项目的编译依赖 方式二:使用Gradle Project 方式三:安装Android Studio插件 gradle view 方式四:如果你嫌在命令行窗口展示观看不友好,这里还有一种体验更好的方式. 输入下面命令行: ./gradlew build --

04-树5 Root of AVL Tree + AVL树操作集

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 illust

PAT 1066 Root of AVL Tree[AVL树][难]

1066 Root of AVL Tree (25)(25 分) 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

HDU 2475 BOX 动态树 Link-Cut Tree 动态树模板

Box Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) [Problem Description] There are N boxes on the ground, which are labeled by numbers from 1 to N. The boxes are magical, the size of each one can be enlarged or r

AVL树模板

1 ///AVL树模板 2 typedef struct Node ///树的节点 3 { 4 int val,data; 5 int h; ///以当前结点为根结点的数的高度 6 int bf; ///平衡因子(左子树高度与右子树高度之差) 7 Node *left,*right; 8 }Node; 9 10 class AvlTree ///alv树,树中太多函数,用类来实现容易一些 11 { 12 private: 13 Node *root; ///树的根节点 14 public: 15

PAT004 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 il

树的平衡 AVL Tree

本篇随笔主要从以下三个方面介绍树的平衡: 1):BST不平衡问题 2):BST 旋转 3):AVL Tree 一:BST不平衡问题的解析 之前有提过普通BST的一些一些缺点,例如BST的高度是介于lgN和N之间的,如果是N的的话,显然效率很低,不是我们需要的:但是在实际情况中,BST的高度h = N的情况却经常出现,例如下图所示.在BST中search,insert的running time都等于BST的高度h,我们肯定希望高度h越小越好,best case就是lgN.下图的example 2的

PAT-1066 Root of AVL Tree(解题报告)

第一次做关于平衡树的题目 第一次做的时候 忘记判断是否是空节点 第二次做,发现LR平衡自己理解错了 对于链式结构理解还是不够深刻,乖乖看书去 题目链接 PAT 1066 附上关于平衡树的四种旋转操作     代码如下: #include<stdio.h> typedef int ElementType; typedef struct AVLTreeNode *AVLTree; typedef struct AVLTreeNode{ ElementType Data; AVLTree Left;

STL源码笔记(18)—平衡二叉树AVL(C++封装+模板)

AVLTree平衡二叉树 在几年前刚学数据结构时,AVL-Tree只是一个仅仅需要掌握其概念的东西,今非昔比,借看STL源码剖析的契机希望从代码层面将其拿下. 1.简介 二叉查找树给我们带来了很多方便,但是由于其在有序序列插入时就会退化成单链表(时间复杂度退化成 O(n)),AVL-tree就克服了上述困难.AVL-tree是一个"加上了平衡条件的"二叉搜索树,平衡条件确保整棵树的深度为O(log n). AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差