一个简单的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

【完】

51单片机-点亮LED和蜂鸣器 ULN2003是高耐压、大电流达林顿陈列,由七个硅NPN达林顿管组成。ULN2003是大电流驱动陈列,多用于单片机、只能仪表、PLC、数字量输出卡等控制电路中。可直接驱动蜂鸣器、继电器等负载。void delay(u16 i) // i等于1大约10uswhile(i--);//取反,高低电平不断变化,产生脉冲delay(10);// 周期200us。 阅读详情

相关推荐

(8)机器人动力学

机器人是一个具有多输入多输出的复杂动力学系统,存在严重的非线性,需要非常系统的方法对机器人进行动力学研究。常用的机器人动力学建模方法有:Lagrange(拉格朗日)动力学方法、Newton-Euler(牛顿-欧拉)动力学方法、Gauss(高斯)动力学方法、Kane(凯恩)动力学方法等。机器人动力学研究的是机器人的运动和作用力之间的关系。机器人的动力学问题包括动力学正问题和动力学逆问题。动力学正问题是对于给定的关节驱动力......

rouyu308的博客 9498

建立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

加湿器方案-DLT8M04TS-杰力科创

基本组成: 一个触摸按键、一组RGB灯、一个雾化片、一个充电IC。 产品功能: 第一次上电光机状态,RGB红/绿/红灯依次闪烁灭; 2、按键功能:短按开关机和三档喷雾工作模式,第一次短按持续喷雾,短按第二次喷3S,停3S,短按第三次关闭喷雾模式,依次循环; 在喷雾或是不喷雾的状态下长按1.5S RGB灯渐变,一直循环,第二次长按当前灯光闪烁一下常亮,第三次长按关机; 3、持续喷雾定时5小时自动断电,间歇喷雾定时10小时自动断电,若在间歇工作时有切换为持续喷雾,那间歇喷雾的...

JLKCsz的博客 512

详解AVL树(平衡二叉树)

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

水澹澹兮生烟 2万+

利用Python实现纬度加权平均(即NCL中的wgt_areaave)

当处理全球数据的时候,最常见的分析就是全球、北半球平均了,这时候一定要注意要根据纬度等信息进行加权,求加权平均,要不然结果肯定会不准。但是对于Python中,常规的计算包里面是没有的,或许现在有其他包可以实现,也可以告诉我~。

记录基于python语言处理气象问题的一些代码,包括不限于气象数据读取、机器学习和深度学习建模。 5744

OpenCV卡尺工具实战:5步搞定工业级圆与直线拟合(附完整C++源码)

本文详细介绍了使用OpenCV卡尺测量工具实现工业级圆与直线拟合的5个关键步骤,包括核心原理、环境配置、边缘点提取优化、鲁棒性几何拟合实现及QT集成技巧。通过模块化C++源码和实战案例,帮助开发者快速掌握高精度尺寸测量技术,适用于机械零件、PCB板等工业检测场景。

uran的专栏 842

数据结构 —— 图解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万+

易康eCognition9.0分类|规则集和机器学习的方法的面向对象的多尺度分割分类

基于易康eCognition9.0软件的规则集和机器学习的方法的面向对象的多尺度分割分类

weixin_46493028的博客 1万+

AVL树(动图详解)

AVL树(C++实现)

2021dragon的博客 2万+

Unity 数字孪生实战:PiXYZ Plugin工业模型高效处理指南

本文是Unity数字孪生实战指南,重点介绍了如何使用PiXYZ Plugin高效处理工业CAD模型。针对工业模型导入Unity时面临的格式壁垒、数据爆炸和资产混乱等核心痛点,文章提供了从环境安装、基础导入到智能减面、资产清理的完整解决方案,并分享了预设自动化、运行时导入等高级技巧与性能优化策略,帮助开发者快速打通工业设计与实时交互流程。

weixin_29009501的博客 256

CATIA二次开发——遍历几何图形集下的轴系及控制轴系生成位置

CATIA二次开发——轴系相关问题1.遍历几何图形集下的轴系2.解决轴系生成位置的问题 1.遍历几何图形集下的轴系 近期遇到的问题:遍历轴系的时候发现,AxisSystem属性的轴系只有放在轴系集合下,才能被找到,放在几何图形集或其他位置均不能被找到。本来想遍历几何图形集下的轴系元素,但是发现没有对应的属性,只能查找 几何图形集、几何元素、草图等元素,无法直接遍历轴系。 解决办法:(加入选择集,在选择集中筛选轴系类型) HybridBody axisHB = activePart.HybridBodies

WorkMan的博客 2730

数据结构--AVL树(全)

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

weixin_48560325的博客 9601

【个人学习总结】CRC校验原理及实现

CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也执行类似的算法,以保证数据传输的正确性和完整性。 ..................

星Yeah 的博客 7967

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

AVLtree的介绍及其简单实现

2301_79296420的博客 1886

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

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

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

喵了个呜的博客 5万+

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

自己实现一个简单的AVL树

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

Stay hungry, Stay foolish 546

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

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、付费专栏及课程。

余额充值