平衡二叉树AVL插入

简介:

平衡二叉树(Balancedbinary tree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskiiand Landis)于1962年首先提出的,所以又称为AVL树。

定义:平衡二叉树或为空树,或为如下性质的二叉排序树:

 (1)左右子树深度之差的绝对值不超过1;

 (2)左右子树仍然为平衡二叉树.

        平衡二叉树可以避免排序二叉树深度上的极度恶化,使树的高度维持在O(logn)来提高检索效率。

 

因为插入节点导致整个二叉树失去平衡分成如下的四种情况:

假设由于在二叉排序树上插入节点而失去平衡的最小子数根节点的指针为a(即a是离插入节点最近,且平衡因子绝对值超过1的祖先节点),则失去平衡后进行调整的规律如下:

1.如上图LL单向右旋处理:由于在*a的左子树根节点的左子树上插入节点,*a的平衡因子由1增至2,致使以*a为根节点的子树失去平衡,则需要进行一次向右的顺时针旋转操作。

2.如上图RR单向左旋处理:由于在*a的右子树根节点的右子树上插入节点, *a的平衡因子有-1变为-2,致使以*a为根节点的子树失去平衡,则学要进行一次向左的逆时针旋转操作。

3.如上图LR双向旋转(先左后右)处理:由于在*a的左子树根节点的右子树插入节点,*a的平衡因子有1增至2,致使以*a为根节点的子树失去平衡,则需要进行两次旋转(先左旋后右旋)操作。

4.如上图RL双向旋转(先右后左)处理:由于在*a的右子树根节点的左子树上插入节点,*a的平衡因子由-1变为-2,致使以*a为根节点的子树失去平衡,则需要进行两次旋转(先左旋后右旋)操作。

复制代码
#include<iostream>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<cstdio>
#define LH 1 //左高 
#define EH 0 //等高 
#define RH -1 //右高 
using namespace std;

template <typename ElemType>
class BSTNode{
    public:
        ElemType data;//节点的数据 
        int bf;//节点的平衡因子
        BSTNode *child[2];
        BSTNode(){
            child[0] = NULL;
            child[1] = NULL;
        }
};

typedef BSTNode<string> BSTnode, *BSTree;

template <typename ElemType>
class AVL{
    public:
        BSTNode<ElemType> *T;
        void buildT();
        void outT(BSTNode<ElemType> *T);
    private:
        bool insertAVL(BSTNode<ElemType>* &T, ElemType key, bool &taller); 
        void rotateT(BSTNode<ElemType>* &o, int x);//子树的左旋或者右旋
        void leftBalance(BSTNode<ElemType>* &o);
        void rightBalance(BSTNode<ElemType>* &o);
};

template <typename ElemType>
void AVL<ElemType>::rotateT(BSTNode<ElemType>* &o, int x){
    BSTNode<ElemType>* k = o->child[x^1];
    o->child[x^1] = k->child[x];
    k->child[x] = o;
    o = k; 
}

template <typename ElemType>
void AVL<ElemType>::outT(BSTNode<ElemType> *T){
    if(!T) return;
    cout<<T->data<<" ";
    outT(T->child[0]);
    outT(T->child[1]);
}

template <typename ElemType>
void AVL<ElemType>::buildT(){
   T = NULL;
   ElemType key;
   while(cin>>key){
           if(key==0) break;
           bool taller = false;
           insertAVL(T, key, taller);
           outT(T);
           cout<<endl;
   }
}

template <typename ElemType>
bool AVL<ElemType>::insertAVL(BSTNode<ElemType>* &T, ElemType key, bool &taller){
    if(!T){//插入新的节点,taller=true 那么树的高度增加 
        T = new BSTNode<ElemType>();
        T->data = key;
        T->bf = EH;
        taller = true;
    } else {
        if(T->data == key){
            taller = false;
            return false;
        }
        if(T->data > key){//向T的左子树进行搜索并插入 
            if(!insertAVL(T->child[0], key, taller)) return false;
            if(taller){//
                switch(T->bf){
                    case LH://此时左子树的高度高,左子树上又插入了一个节点,失衡,需要进行调整 
                        leftBalance(T);
                        taller = false;//调整之后高度平衡 
                        break; 
                    case EH:
                        T->bf = LH;
                        taller = true;
                        break; 
                    case RH:
                        T->bf = EH;
                        taller = false;                        
                        break;
                }
            }
        } 
        if(T->data < key) {//向T的右子树进行搜索并插入 
            if(!insertAVL(T->child[1], key, taller)) return false;
            switch(T->bf){
                case LH:
                    T->bf = EH;
                    taller = false; 
                    break; 
                case EH:
                    T->bf = RH;
                    taller = true;
                    break; 
                case RH:
                    rightBalance(T);    
                    taller = false;                    
                    break;
            }
        }
    }
    return true;
}

template <typename ElemType>
void AVL<ElemType>::leftBalance(BSTNode<ElemType>* &T){
    BSTNode<ElemType>* lchild = T->child[0];
    switch(lchild->bf){//检查T的左子树的平衡度,并作相应的平衡处理 
        case LH://新节点 插入到 T的左孩子的左子树上,需要对T节点做单旋(右旋)处理 
            T->bf = lchild->bf = EH; 
            rotateT(T, 1);
            break;
        case RH://新节点 插入到 T的左孩子的右子树上,需要做双旋处理  1.对lchild节点进行左旋,2.对T节点进行右旋 
            BSTNode<ElemType>* rdchild = lchild->child[1];
            switch(rdchild->bf){//修改 T 及其左孩子的平衡因子 
                case LH: T->bf = RH; lchild->bf = EH; break;
                case EH: T->bf = lchild->bf = EH; break;//发生这种情况只能是 rdchild无孩子节点
                case RH: T->bf = EH; lchild->bf = LH; break; 
            }
            rdchild->bf = EH; 
            rotateT(T->child[0], 0);//不要写成 rotateT(lc, 0);//这样的话T->lchild不会改变 
            rotateT(T, 1);
            break;
    }
}

template <typename ElemType>
void AVL<ElemType>::rightBalance(BSTNode<ElemType>* &T){
    BSTNode<ElemType>* rchild = T->child[1];
    switch(rchild->bf){//检查T的左子树的平衡度,并作相应的平衡处理 
        case RH://新节点 插入到 T的右孩子的右子树上,需要对T节点做单旋(左旋)处理 
            T->bf = rchild->bf = EH; 
            rotateT(T, 0);
            break;
        case LH://新节点 插入到 T的右孩子的左子树上,需要做双旋处理  1.对rchild节点进行右旋,2.对T节点进行左旋 
            BSTNode<ElemType>* ldchild = rchild->child[0];
            switch(ldchild->bf){//修改 T 及其右孩子的平衡因子 
                case LH: T->bf = EH; rchild->bf = RH; break;
                case EH: T->bf = rchild->bf = EH; break;//发生这种情况只能是 ldchild无孩子节点 
                case RH: T->bf = LH; rchild->bf = EH; break; 
            }
            ldchild->bf = EH; 
            rotateT(T->child[1], 1);
            rotateT(T, 0);
            break;
    }
}

int main(){
    AVL<int> avl;
    avl.buildT();
    avl.outT(avl.T);
    return 0;
} 

/*
 13 24 37 90 53 0
*/









本文转自 小眼儿 博客园博客,原文链接:http://www.cnblogs.com/hujunzheng/p/4665451.html,如需转载请自行联系原作者
目录
相关文章
|
2月前
|
人工智能 自然语言处理 Cloud Native
阿里云开发者必读:2026年 Copilot 和 Cursor 的平替推荐排行榜 (Java与云原生专版)
随着 Qwen-2.5-Coder 等国产开源模型的爆发,国内 AI 编程工具已在性能上对标甚至反超国际竞品。对于深耕国内业务、尤其是使用 Java/Go 技术栈和阿里云设施的企业而言,寻找 Copilot 和 Cursor 的平替推荐 已不再是“降级替代”,而是“体验升级”。
阿里云开发者必读:2026年 Copilot 和 Cursor 的平替推荐排行榜 (Java与云原生专版)
|
6月前
|
存储 监控 数据可视化
大模型可观测1-5-10:发现、定位、恢复的三层能力建设
本文通过丰富的代码Demo和截图为读者提供了可落地的实践指南。
816 34
大模型可观测1-5-10:发现、定位、恢复的三层能力建设
|
关系型数据库 Linux Apache
|
9月前
|
前端开发 测试技术 API
一文掌握软件分支管理
本文详细介绍了软件分支管理的实践经验,结合具体项目案例,从版本号、分支命名、标签管理到合并策略等方面展开。通过清晰的规则和流程图示,帮助团队避免版本混乱,提升研发效率。强调主干与开发分支的核心作用,同时提醒合理控制分支数量,确保协作顺畅。适用于不同类型的项目,助力团队建立适合自身的版本管理体系。
1400 69
一文掌握软件分支管理
|
3月前
|
存储 人工智能 安全
AICoding实践:从Prd到代码生成
本文探讨了在AI技术推动软件工程范式变革的新阶段,如何通过构建增强型AI编程系统(codefuse)实现从需求到代码的端到端自动生成。
1190 21
AICoding实践:从Prd到代码生成
|
9月前
|
人工智能 监控 中间件
深入解析|Cursor编程实践经验分享
本文是近两个月的实践总结,结合在实际工作中的实践聊一聊Cursor的表现。记录在该过程中遇到的问题以及一些解法。问题概览(for 服务端): 不如我写的快?写的不符合预期? Cursor能完成哪些需求?这个需求可以用Cursor,那个需求不能用Cursor? 历史代码分析浅显,不够深入理解? 技术方案设计做的不够好,细节缺失,生成代码的可用性不够满意?
1759 10
深入解析|Cursor编程实践经验分享
|
8月前
|
机器学习/深度学习 人工智能 算法
通义WebSailor开源,检索性能登顶开源榜单!
通义开源网络智能体WebSailor具备强大推理与检索能力,在复杂场景下表现优异,已登顶开源网络智能体榜单。其创新训练方法大幅提升了模型性能,适用于多领域复杂任务。
817 0
通义WebSailor开源,检索性能登顶开源榜单!
|
弹性计算 监控 安全
打造安全云环境:深入理解阿里云权限体系
本文将探讨阿里云上的权限管理,帮助理解其背后原理并掌握实践方法。主要内容分为三部分:一是访问控制基本原理,强调避免使用root身份,介绍权限策略语言和类型;二是五种典型的授权方式,包括服务级、操作级和资源级授权等;三是多账号环境下的集中化权限管理,重点介绍如何使用管控策略实现安全合规的集中管控。通过这些内容,用户可以更好地理解和应用阿里云的权限管理体系,确保云资源的安全与高效管理。
|
人工智能 算法 前端开发
阿里通义灵码的最佳实践
上周首次尝试了阿里巴巴的通义灵码AI插件,体验良好。该插件体积适中,约5.8M,适合项目开发使用。其@workspace和@terminal功能强大,能快速帮助开发者熟悉新项目结构,提供智能代码导航、搜索、优化及错误提示等服务,显著提升开发效率与代码质量。实践证明,通义灵码在加速项目理解和新需求实现方面表现出色,是开发者的得力助手。
663 1
阿里通义灵码的最佳实践
|
人工智能 搜索推荐 API
用于企业AI搜索的Bocha Web Search API,给LLM提供联网搜索能力和长文本上下文
博查Web Search API是由博查提供的企业级互联网网页搜索API接口,允许开发者通过编程访问博查搜索引擎的搜索结果和相关信息,实现在应用程序或网站中集成搜索功能。该API支持近亿级网页内容搜索,适用于各类AI应用、RAG应用和AI Agent智能体的开发,解决数据安全、价格高昂和内容合规等问题。通过注册博查开发者账户、获取API KEY并调用API,开发者可以轻松集成搜索功能。