一个简单的AVL树实现

AVL树的动态演示与快速构建 本文讨论的AVL树算法的动态演示除了考虑怎样实现在网上传输外,更重要的是要考虑如何将抽象的算法形象生动的再现。 立即下载

上一篇文章实现了一个最简单的二叉搜索树,里面理由两个成员函数:插入和中序遍历。我觉得,插入应该算是BSTreet中最核心的一个函数了。
二叉搜索树虽然是一颗排序树,但当数据的插入顺序基本逆序时,BSTreet就退化为一个很近似链表的结构。而链表中查找的时间复杂度为O(n),显然这失去了二叉搜索树O(lgN)的优势。
因此我们可以对BSTree进行改进,使之成为一个平衡的二叉搜索树,即AVL树。
AVL树的特点是:
* 左子树和右子树的高度之差不超过1;
* 左子树和右子树都是AVL树;

当我们插入一个数,使得AVL树不满足以上条件时,需要对其进行旋转。具体可见如下代码:

#pragma once

#include<iostream>
using namespace std;

namespace NonRecursion
{
    template<typename K,typename V>
        struct AVLTreeNode{
            K _key;
            V _value;
            AVLTreeNode<K,V>* _parent;
            AVLTreeNode<K,V>* _left;
            AVLTreeNode<K,V>* _right;
            int _bf;
            AVLTreeNode(const K& key,const V& value)
                :_key(key),_value(value),_parent(NULL),_left(NULL),_right(NULL),_bf(0)
            {}
        };

    template<typename K,typename V>
        class AVLTree{
            typedef AVLTreeNode<K,V> Node;
            public:
            AVLTree()
                :_root(NULL)
            {}
            ~AVLTree()
            {
                _erase(_root);
            }
            bool Insert(const K& key,const V& value)
            {
                //1.空树
                //2.查找位置
                //3.插入节点
                //4.更新平衡因子,调整树
                //5.如果进行了旋转调整,则将parent进行重新连接
                if(_root==NULL)
                {
                    _root=new Node(key,value);
                    return true;
                }
                Node* parent=NULL;
                Node* cur=_root;
                //插入节点
                while(cur!=NULL)
                {
                    if(cur->_key<key)
                    {
                        parent=cur;
                        cur=cur->_right;
                    }
                    else if(cur->_key>key)
                    {
                        parent=cur;
                        cur=cur->_left;
                    }
                    else
                        return false;
                }
                cur=new Node(key,value);
                if(parent->_key<key)
                    parent->_right=cur;
                else
                    parent->_left=cur;
                cur->_parent=parent;

                //调节平衡因子
                while(parent!=NULL)
                {
                    if(cur==parent->_left)
                        parent->_bf--;
                    else
                        parent->_bf++;

                    /* parent->_bf==0:break;
                     * parent->_bf==1/-1:continue go up;
                     * parent->_bf==2/-2:rotate;
                     */
                    if(parent->_bf==0)
                        break;
                    else if(parent->_bf==1 || parent->_bf==-1)
                    {
                        cur=parent;
                        parent=parent->_parent;
                    }
                    else //parent->_bf==2/-2
                    {
                        if(parent->_bf==2)
                        {
                            if(cur->_bf==1)
                                _RotateL(parent);
                            else
                                _RotateRL(parent);
                        }
                        else
                        {
                            if(cur->_bf==-1)
                                _RotateR(parent);
                            else
                                _RotateLR(parent);
                        }
                        break;
                    }
                }
                return true;
            }
            Node* Find(const K& key)
            {
                Node* cur=_root;
                while(cur!=NULL)
                {
                    if(cur->_key==key)
                        return cur;
                    else if(cur->key>key)
                        cur=cur->_left;
                    else
                        cur=cur->_right;
                }
                return NULL;
            }
            void InOrder()
            {
                _InOrder(_root);
                cout<<endl;
            }
            bool IsBalance()
            {
                int depth=0;
                return _IsBalance(_root,depth);
            }
            bool Remove(const K& key);
            //////////////////////////////////////////////////////////////////////////////////
            protected:
            bool _IsBalance(Node* root,int& depth)
            {
                if(root==NULL)
                {
                    depth=0;
                    return true;
                }
                int left,right;
                if(_IsBalance(root->_left,left) && _IsBalance(root->_right,right))
                {
                    depth=left>right?left+1:right+1;
                    if(root->_bf==right-left)
                        return true;
                    else
                        return false;
                }
                return false;
            }
            void _InOrder(Node* root)
            {
                if(root==NULL)
                    return;
                _InOrder(root->_left);
                cout<<root->_key<<" ";
                _InOrder(root->_right);
            }
            void _RotateL(Node* root)
            {
                if(root==NULL)
                    return;
                Node* parent=root;
                Node* subR=parent->_right;
                Node* subRL=subR->_left;
                parent->_right=subRL;
                if(subRL!=NULL)
                    subRL->_parent=parent;
                Node* ppNode=parent->_parent;
                subR->_left=parent;
                parent->_parent=subR;
                if(ppNode!=NULL)
                {
                    if(ppNode->_left==parent)
                        ppNode->_left=subR;
                    else
                        ppNode->_right=subR;
                }
                else
                {
                    _root=subR;
                }
                subR->_parent=ppNode;
                parent->_bf = subR->_bf = 0;
                //parent->_bf--;
                //subR->_bf--;
            }
            void _RotateR(Node* root)
            {
                if(root==NULL)
                    return;
                Node* parent=root;
                Node* subL=parent->_left;
                Node* subLR=subL->_right;
                parent->_left=subLR;
                if(subLR!=NULL)
                    subLR->_parent=parent;
                Node* ppNode=parent->_parent;
                subL->_right=parent;
                parent->_parent=subL;
                if(ppNode!=NULL)
                {
                    if(ppNode->_left==parent)
                        ppNode->_left=subL;
                    else
                        ppNode->_right=subL;
                }
                else
                {
                    _root=subL;
                }
                subL->_parent=ppNode;
                parent->_bf = subL->_bf = 0;
                //parent->_bf++;
                //subL->_bf++;
            }
            void _RotateRL(Node* root)
            {
                if(root==NULL)
                    return;
                Node* parent=root;
                Node* subR=parent->_right;
                Node* subRL=NULL;
                if(subR!=NULL)
                    subRL=subR->_left;
                _RotateR(subR);
                _RotateL(parent);
            }
            void _RotateLR(Node* root)
            {
                if(root==NULL)
                    return;
                Node* parent=root;
                Node* subL=parent->_left;
                _RotateL(subL);
                _RotateR(parent);
            }
            void _erase(Node* root)
            {
                if(root==NULL)
                    return;
                _erase(root->_left);
                _erase(root->_right);
                delete root;
            }
            private:
            Node* _root;
        };
}

以上

如果你有任何想法或是可以改进的地方,欢迎和我交流!

完整代码及测试用例在github上:点我前往

本文首发于www.sbrave.cn

【完】

Maven证书信任危机:PKIX path building failed的全面解析与实战修复 本文全面解析了Maven构建中常见的`PKIX path building failed`证书验证错误。该错误通常在使用特定镜像仓库或自建仓库时,因SSL/TLS证书不被JDK默认信任而触发。文章深入剖析了错误根源,对比了临时忽略检查与永久导入证书等不同修复方案的安全性与适用场景,并推荐通过`keytool`将证书导入JDK信任库的根治方法,以保障构建安全与稳定。 阅读详情

相关推荐

OPCUA二(通过OPCUA服务器访问CPU)

摘要:本文介绍了使用UaExpert软件连接西门子PLC的OPC UA配置方法,包括IP地址设置(默认端口4840)、安全认证和证书信任流程。详细说明了数据访问操作,如变量拖拽监控和属性解读(NodeId、Value、状态码等)。特别强调连接仿真Advance7时需先启动实例。最后预告下章将讲解通过KerServer访问CPU。文章涵盖配置步骤、常见问题处理及实用技巧,适合工业自动化开发者参考。

欢迎来到RaymondLeigh的知识共享基地 1337

建立AVL树并用前序的方式输出

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <malloc.h> #include <math.h> typedef struct AVLtree { char element; int height; struct AVLtree* left; struct AVLtree* right; }AVLTREE; typed.

LuciferFISH的博客 335

AFSim 2.9实战指南:从入门到精通的中文教程

本文是AFSim 2.9的实战中文教程,旨在帮助用户从零开始掌握这一先进的仿真框架。内容涵盖从环境安装、运行第一个“Hello World”仿真,到深入理解实体、组件、想定编辑器等核心概念,并进阶探讨动力学建模、传感器仿真与红蓝对抗想定构建。最后,指南还提供了效能分析与实战排错技巧,帮助用户将仿真结果转化为有价值的量化数据,适用于军事、航空航天等领域的复杂系统行为模拟研究。

weixin_29294395的博客 355

详解AVL树(平衡二叉树)

插入节点后对树进行旋转调整,分为四种情况。 1.右单旋 当一个平衡二叉树满足具有较高左子树时(如下图A),且要插入的节点插入到了较高左子树的左侧,此时进行右单旋。

水澹澹兮生烟 2万+

中断向量表配置不当引发Default_Handler死循环问题解析

本文深入解析STM32开发中因中断向量表配置不当导致的Default_Handler死循环问题。以STM32F407VET6为例,详细阐述中断向量表的工作原理、常见触发场景及系统化排查方法,并提供使用STM32CubeMX的正确姿势和手动配置的注意事项,帮助开发者快速定位并解决这一常见难题。

grafana6viz的博客 179

VS2022离线环境下的NuGet包管理:从本地源到依赖项全解析

本文详细解析了在VS2022离线环境下如何高效管理NuGet包,包括搭建本地NuGet源的两种方案(本地文件夹源和私有NuGet服务器)、获取离线包的三大渠道以及依赖项处理的实战技巧。通过自动化脚本和依赖树分析工具,帮助开发者解决离线环境中的依赖项黑洞问题,提升开发效率。

5f4d3s2a1q的博客 1060

数据结构 —— 图解AVL树(平衡二叉树)

文章目录1、AVL树(平衡二叉树)的定义1.1、平衡因子2、AVL树的作用:3、AVL树的基本操作3.1、插入—— 左左型的右旋:3.1.1、右旋的具体步骤:3.1.2、右旋的动画演示:3.1.3、右旋示例:3.2、插入——右右型的左旋:3.2.1、左旋的具体步骤:3.2.2、动画演示:3.2.3、左旋举例:3.3、插入——左右型的左右旋 ( 即先左后右):3.3.1、左右旋的两次旋转步骤:3.3...

猎人在吃肉 6万+

【PLL】分频器设计权衡:从CMOS到CML的电路实现与优化

本文深入探讨了PLL中分频器的设计权衡,比较了CMOS和CML两种电路实现的优缺点。通过实际案例分析,展示了如何在速度、功耗和噪声之间取得平衡,特别是在5G射频芯片和Wi-Fi 6E等高频应用中的优化实践。文章还提供了混合架构设计和电源噪声协同优化的实用技巧,适合电路设计工程师参考。

weixin_42521843的博客 442

AVL树(动图详解)

AVL树(C++实现)

2021dragon的博客 2万+

9.16华为OD机试真题 新系统 - 矩阵螺旋遍历 (Java/Py/C/C++/Js/Go)

9.16华为OD机试真题 新系统 - 矩阵螺旋遍历 (Java/Py/C/C++/Js/Go)

算法大师! 644

RuntimeError: The current installed version of g++ (4.8.5) is less than the mininum version CUDA解决方案

本文主要介绍了RuntimeError: The current installed version of g++ (4.8.5) is less than the mininum version CUDA解决方案,希望能对学习python的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 8万+

数据结构--AVL树(全)

目录 什么是AVL树? AVL树的特点及形成原因 二叉搜索树基本概念 二叉搜索的特点 二叉搜索树的优点及缺点 改进的二叉搜索树——AVL树 AVL树的定义 AVL树的特点 结点的平衡因子balance 构建一个AVL树 构建一个AVL树的节点 什么是AVL树? AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。 AVL树的特点及形成原因 AVL树本质.

weixin_48560325的博客 9601

【Unity大规模RTS/攻城战框架】Large Scale Combat System - RTS Sieges深度解析

本文介绍了Unity专业级大规模RTS战斗框架Large Scale Combat System(LSCS)。该系统通过Job System+Burst技术解决了万人级单位的性能问题,提供完整的RTS操作体系、动态阵型系统、战术AI和攻城战功能。其亮点包括可破坏城门、行走城墙、战术AI配置系统,支持URP渲染管线,适用于Total War风格的大规模兵团对战项目。LSCS不仅提供核心战斗系统,还包含UI、小地图等配套模块,是Unity中少有的专业级RTS解决方案,特别适合需要深度战术玩法和大规模战斗的开发者

2403_88403568的博客 1334

C++ AVL树的介绍及简单实现

AVLtree的介绍及其简单实现

2301_79296420的博客 1886

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

AVL树的旋转图解和简单实现

AVL树是带有平衡条件的查找二叉树。这个平衡条件要容易保持,而且他要保证树的深度为O(logN) 原文地址:http://blog.csdn.net/qq_25806863/article/details/74755131 平衡条件 一个最理想的平衡条件是左右两个子树的高度完全相等,但只有节点数量为2^n-1的树才满足这个条件(n是层数,2层要3个,3层要7个)。这个条件太严格,不好用。...

喵了个呜的博客 5万+

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

自己实现一个简单的AVL树

自己实现一个简单的AVL-Tree。

Stay hungry, Stay foolish 546

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

c++简单实现avl树

这里我选择的是右子树-左子树作为平衡因子,有平衡因子更方便实现。节点类:更好的管理节点。大了往左找,小了往右找。

dabai__a的博客 1253

AVL树的插入删除详细实现,基于AVL树的map和set简单模板编程实现,包括const迭代器

以上,我们就完成了插入操作,与它不同的是,删除操作就算旋转完了也要继续向上维护父节点,直到整棵树的根部,并且我们如果删除了还要旋转,那就要旋转类似红黑树里的那个"uncle"节点,也就是父亲的另一个节点,如果这个节点不存在删除后是不可能引起旋转的,具体原因依旧可以去找视频看,这里只提供代码。如此操作,我们便使得data适配了一个单一类型以及一个pair类型,我们甚至可以通过继续定义T塞入更多的数据,这为我们的模板编程开启了一个新的大门,是我认为map中一个很强大的东西。不禁要问,为什么要这样写呢?

2401_88830544的博客 800

AVL树的简单实现

class Node{ int key; int bf; Node left; Node right; Node parent; public Node(int key,Node parent){ this.key=key; this.parent=parent; } } class AVLTree{ public Node root; public void insert(int key){

Mainhxj的博客 219

AVL树了解并简单实现

AVL树就是在二叉搜索树的基础上引入了平衡因子,因此AVL树也可以看成是二叉搜索树。那么按照二叉搜索树的方式插入新节点调整节点的平衡因子平衡因子 = 右子树高度 - 左子树高度插入的新结点newNode在当前结点cur的左子树,平衡因子--插入的新结点newNode在当前结点cur的右子树,平衡因子++是否要往上更新祖先的平衡因子,要看cur的parent结点所在高度是否发生变化。

wrf228的博客 1113

C++之AVL树的简单实现

AVL树是一个自平衡二叉树,其满足任意节点的左右子树高度差(称为 “平衡因子”)的绝对值 ≤ 1。平衡因子=右子树高度-左子树高度。(当然也可以是左子树高度-右子树高度,这里用右-左讲解通过平衡因子的约束,AVL树能够有效维持二叉树的查询 / 插入 / 删除效率。

2402_88062890的博客 1130

AVL 树的理解和简单实现

这样可以提供更好的性能和效率。旋转处理的情况分为四种:左单旋、右单旋、左右双旋、右左双旋;旋转的原则:旋转后仍是一颗AVL树;旋转的目的:左右均衡,降低整棵AVL树的高度。

m0_62229058的博客 849

【C++】AVL树的简单实现

AVL树是为了弥补搜索树插入时,效率问题而提出来的一种树形结构二叉搜索树在搜索时的效率比较高是O(logH),也就是说搜索树的搜索效率依赖于树的高度,当搜索树插入数据是有序或者接近有序时,树的高度是N(有N个数据),搜索效率就会退化到O(N),因此要提高搜索树的效率,就是要尽量使树的高度低,AVL树就是一颗高度平衡的二叉搜索树。

m0_62179366的博客 556

C语言基于AVL树实现简单的文件数据库

本文是对AVL树的一个简单应用,在资源偏紧张的硬件设备中可以使用,如资源足够还是建议使用sqlite。

SauryN的博客 435

AVL树的删除方法简单实现

看过前面的AVL树的介绍和插入方法实现,接着可以来学习删除方法的实现。

wrf228的博客 1302
上一篇: 冒泡排序
下一篇: 一个简单的二叉搜索树实现
SmartBrave
博客等级 码龄12年 25粉丝 69原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值