平衡二叉树(AVL树)的插入、删除

数据结构与算法3 AVL树 将 26, 13, 44, 51, 98, 37, 66, 73 顺序插入一棵初始为空的AVL树。将 7, 8, 9, 2, 3, 5, 6, 4 顺序插入一棵初始为空的AVL树。在将{42,26,8,70,102,56,2}插入一个初始空的 AVL 树时,下列哪个语句为真?如果节点{1,2,3,4}的 AVL 树的深度为3(根的深度为1) ,那么节点4可能是根。将2,1,4,5,9,3,6,7插入到一个初始的空 AVL 树中。非空的平衡二叉树中插入一个结点,原有结点中至少一个结点的平衡因子会改变。 阅读详情

AVL树主要难点在于,插入和删除,因为插入和删除后需要对树进行调整使其仍满足AVL树的要求,具体的调整过程网上都有就不细讲了,主要是删除部分很少有书进行讲解,可以参考一下:

http://www.cppblog.com/cxiaojia/archive/2012/08/20/187776.html

我的删除部分代码:可以看看为什么在删除一个结点后采用这种调整方式,博主也是看了好久才明白,一定要用手画平衡二叉树然后根据代码进行删除来验证一下是否正确,二叉树的插入和删除我整整写了两天-_-

AVLTree Delete(AVLTree T, int x)
{
    AVLTree temp;
    if (T)        //树不为空
    {
        if (x < T->value)  //X小于该结点
        {
            T ->left = Delete(T->left, x); //如果x小于结点的值就继续在结点的左子树中递归删除

            if (GetHight(T->right) - GetHight(T->left) == 2)
            {
                if (T->right->left != NULL && GetHight(T->right->left) > GetHight(T->right->right))
                {
                    T = DoubleRightLeftRotation(T); //R-L
                }
                else
                {
                    T = SingleRightRotation(T);    //R-R
                }
            }
        }

        else if (x > T->value)  //X值大于该结点
        {
            T->right = Delete(T->right, x); //如果X大于结点的值就继续在结点的右子树递归删除

            if (GetHight(T->left) - GetHight(T->right) == 2)
            {
                if (T->left->right != NULL && GetHight(T->left->right) > GetHight(T->left->left))
                {
                    T = DoubleLeftRightRotation(T);  //L-R
                }
                else
                {
                    T = SingleLeftRotation(T);   //L-L
                }
            }
        }
        else  //X等于该结点,即为该删除的结点
        {
            if (T->left && T->right) //此结点有两个儿子
            {
                /*用右子树的最小值来代替被删除的结点*/
                temp = T->right;
                while (temp->left != NULL)
                {
                    temp = temp->left;
                }
                T->value = temp->value;
                T->right = Delete(T->right, temp->value);
                if (GetHight(T->left) - GetHight(T->right) == 2)
                {
                    if (T->left->right && GetHight(T->left->right) > GetHight(T->left->left))
                    {
                        T = DoubleLeftRightRotation(T);  //L-R
                    }
                    else
                    {
                        T = SingleLeftRotation(T);   //L-L
                    }
                }
            }

            else //此结点有一个或者没有儿子
            {
                temp = T;
                if (T->left == NULL) //有右儿子或者没有儿子
                {
                    T = T->right;
                }
                else
                {
                    T = T->left;
                }
                free(temp);
            }
        }
    }

    T->hight = Max(GetHight(T->left), GetHight(T->right)) + 1;
    return T;
}

 完整的代码如下:

/************************************************************************
*
* 文件名:4.2.1.cpp
*
* 文件描述:平衡二叉树(AVL树)的插入、删除
*
* 创建人:  fdk

* 时  间:  2018-08-09
*
* 版本号:1.0
*
* 修改记录:修改了很多次-_-
*
************************************************************************/
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <stack>
#include <time.h>
#include <queue>
using namespace std;

/*定义树的结构*/
typedef struct AVLNode
{
    int value;             //结点数据
    struct AVLNode *left;  //指向左子树
    struct AVLNode *right; //指向右子树
    int hight;             //树高
}*AVLTree, AVL_Tree;

/*返回最大值*/
int Max(int a, int b)
{
    return a > b ? a:b;
}

/*求二叉树的高度*/
int GetHight(AVLTree T)
{
    if (T)
    {
        return (T->hight);             //返回树的高度
    }
    else
    {
        return 0;    //空树高度为0
    }
}

/*LL旋转-(左单旋)*/
AVLTree SingleLeftRotation(AVLTree A)
{
    /*将A与B做LL旋转,更新A与B的高度,返回新的根结点B*/
    AVLTree B = A->left;
    A->left = B->right;
    B->right = A;
    A->hight = Max(GetHight(A->left), GetHight(A->right)) + 1;
    B->hight = Max(GetHight(B->left), A->hight) + 1;
    return B;
}

/*RR旋转-(右单旋)*/
AVLTree SingleRightRotation(AVLTree A)
{
    /*将A与B做RR旋转,更新A与B的高度,返回新的根结点B*/
    AVLTree B = A->right;
    A->right = B->left;
    B->left = A;
    A->hight = Max(GetHight(A->left), GetHight(A->right)) + 1;
    B->hight = Max(GetHight(B->right), A->hight) + 1;
    return B;
}

/*LR旋转(左-右双旋)*/
AVLTree DoubleLeftRightRotation(AVLTree A)
{
    /*LR就相当于做了两次单旋,先是右单旋转,再是左单旋转*/
    A->left = SingleRightRotation(A->left);  //右单旋转

    return SingleLeftRotation(A);           //左单旋转
}

/*RL旋转(右-左双旋)*/
AVLTree DoubleRightLeftRotation(AVLTree A)
{
    /*RL就相当于做了两次单旋,先是左单旋转,再是右单旋转*/
    A->right = SingleLeftRotation(A->right); //左单旋转
    return SingleRightRotation(A);
}

/*插入*/
AVLTree Insert(AVLTree T, int x)
{
    /*将x插入到AVL树中,并且返回调整后的AVL树*/
    if (T == NULL)
    {
        /*若树为空树,则新建包含一个结点的树*/
        T = (AVLTree)malloc(sizeof(AVL_Tree));
        T->value = x;
        T->hight = 1;
        T->left = NULL;
        T->right = NULL;
    }
    else
    {
        if (x < T->value)
        {
            /*插入T的左子树*/
            T->left = Insert(T->left, x);

            /*如果需要左旋*/
            if (GetHight(T->left) - GetHight(T->right) == 2)
            {
                if (x < T->left->value)
                {
                    T = SingleLeftRotation(T);  //左单旋
                }
                else
                {
                    T = DoubleLeftRightRotation(T); //左-右双旋
                }
            }
        }
        else if (x > T->value)
        {
            /*插入右子树*/
            T->right = Insert(T->right, x);

            /*如果需要右旋*/
            if (GetHight(T->right) - GetHight(T->left) == 2)
            {
                if (x > T->right->value)
                {
                    T = SingleRightRotation(T);     //右单旋
                }
                else
                {
                    T = DoubleRightLeftRotation(T);  //右-左旋转
                }
            }
        }
        else
        {
            cout << "该结点已存在!" << endl;
        }
    }
    T->hight = Max(GetHight(T->left), GetHight(T->right)) + 1; //更新树高
    return T;
}

/*删除结点*/
AVLTree Delete(AVLTree T, int x)
{
    AVLTree temp;
    if (T)        //树不为空
    {
        if (x < T->value)  //X小于该结点
        {
            T ->left = Delete(T->left, x); //如果x小于结点的值就继续在结点的左子树中递归删除

            if (GetHight(T->right) - GetHight(T->left) == 2)
            {
                if (T->right->left != NULL && GetHight(T->right->left) > GetHight(T->right->right))
                {
                    T = DoubleRightLeftRotation(T); //R-L
                }
                else
                {
                    T = SingleRightRotation(T);    //R-R
                }
            }
        }

        else if (x > T->value)  //X值大于该结点
        {
            T->right = Delete(T->right, x); //如果X大于结点的值就继续在结点的右子树递归删除

            if (GetHight(T->left) - GetHight(T->right) == 2)
            {
                if (T->left->right != NULL && GetHight(T->left->right) > GetHight(T->left->left))
                {
                    T = DoubleLeftRightRotation(T);  //L-R
                }
                else
                {
                    T = SingleLeftRotation(T);   //L-L
                }
            }
        }
        else  //X等于该结点,即为该删除的结点
        {
            if (T->left && T->right) //此结点有两个儿子
            {
                /*用右子树的最小值来代替被删除的结点*/
                temp = T->right;
                while (temp->left != NULL)
                {
                    temp = temp->left;
                }
                T->value = temp->value;
                T->right = Delete(T->right, temp->value);
                if (GetHight(T->left) - GetHight(T->right) == 2)
                {
                    if (T->left->right && GetHight(T->left->right) > GetHight(T->left->left))
                    {
                        T = DoubleLeftRightRotation(T);  //L-R
                    }
                    else
                    {
                        T = SingleLeftRotation(T);   //L-L
                    }
                }
            }

            else //此结点有一个或者没有儿子
            {
                temp = T;
                if (T->left == NULL) //有右儿子或者没有儿子
                {
                    T = T->right;
                }
                else
                {
                    T = T->left;
                }
                free(temp);
            }
        }
    }

    T->hight = Max(GetHight(T->left), GetHight(T->right)) + 1;
    return T;
}

/*中序递归遍历*/
void InorderTraversal(AVLTree T)
{
    if (T)
    {
        InorderTraversal(T->left);
        cout << T->value << " ";
        InorderTraversal(T->right);
    }
}

/*中序递归遍历*/
void PreorderTraversal(AVLTree T)
{
    if (T)
    {
        cout << T->value << " ";
        PreorderTraversal(T->left);
        PreorderTraversal(T->right);
    }
}

int main()
{
    AVLTree T = NULL;
    int a[] = {80, 50, 100, 40, 60, 90, 140, 45, 83, 95, 150, 81};
    int lengths = sizeof(a) / sizeof(a[0]);
    for (int i = 0; i < lengths; i++)
    {
       T = Insert(T, a[i]);
    }
    cout << "前序递归遍历:";
    PreorderTraversal(T);
    cout << endl;

    cout << "中序递归遍历:";
    InorderTraversal(T);
    cout << endl;

    cout << "删除140结点";
    Delete(T, 140);
    cout << endl;

    cout << "前序递归遍历:";
    PreorderTraversal(T);
    cout << endl;

    cout << "中序递归遍历:";
    InorderTraversal(T);
    cout << endl;
    return 0;
}

 

平衡二叉树(AVL树)的平衡原理以及插入,删除操作 文章目录AVL树的定义AVL树不平衡的情况左子树的左子树插入结点 (左左)右子树的右子树插入节点左子树的右子树插入节点右子树的左子树插入节点删除结点插入节点更复杂的情况所有代码测试结果 AVL树的定义 平衡因子 : 树中某结点其左子树的高度和右子树的高度之差 AVL树中的任意一个结点, 其平衡因子的绝对值小于2 AVL树是一种特殊的二叉搜索树 (BST树), 相对于数据极端情况下, 二叉搜索树会... 阅读详情

相关推荐

平衡二叉树(AVL)的插入和删除详解(下)

平衡二叉树(AVL)的插入和删除详解(上):http://blog.youkuaiyun.com/sysu_arui/article/details/7897017 1、测试代码 为减小篇幅,只给出了主程序,其他函数模块请看(上)中的描述。 #include #include #include using namespace std; int main(int argc, char *ar

arui的专栏 4782

AVL Tree | Set 2 (Deletion)

原文链接:https://www.geeksforgeeks.org/avl-tree-set-2-deletion/ Steps to follow for deletion. To make sure that the given tree remains AVL after every deletion, we must augment the standard BST delete ope...

hellobettershero的博客 483

平衡二叉树AVL的c++实现

1 先创建节点类,就是一个普通的节点类的创建,用结构体也可以,唯一值的注意的是要有一个表示当前节点高度的成员,因为节点高度是判断平衡二叉树是否平衡的标志。#include &lt;iostream&gt; using namespace std;template&lt;class T&gt;class TreeNode{public:    T val;    TreeNode&lt;T&gt;*...

qq_36101436的博客 3105

AVL tree

/* avlLib.h - AVL trees library header file */ /* Copyright 1999 Wind River Systems, Inc. */ /* modification history -------------------- 01e,10feb00,abd added avlMinimumGet and avlMaximumGet 01d,1...

danxibaoxxx的博客 400

AVL树的删除、增加节点的程序

该程序包含AVL树的增加节点和删除节点的操作,用户根据提示先建立一颗AVL树,然后选择是删除节点操作还是增加节点操作来进行选择。

保姆级教程:用CST 2023一步步复现一个1-8GHz Vivaldi天线(含参数优化与结果分析)

本文提供了一份详细的CST 2023教程,指导读者如何从零开始设计并优化1-8GHz Vivaldi天线。内容涵盖工程设置、参数化建模、仿真加速技巧以及性能优化策略,特别适合需要实现宽带天线设计的工程师和研究人员。通过实战案例,帮助用户掌握Vivaldi天线的核心设计要点和CST高级功能应用。

weixin_30800987的博客 618

【高阶数据结构】平衡二叉树(AVL)的删除和调整

平衡二叉树节点的删除方法详细讲解;平衡二叉树的删除代码实现(C++);

更新C/C++,数据结构与算法,计算机视觉,深度学习,目标检测 2225

世界职业院校技能大赛财经赛道项目参考逐字稿五

世界职业院校技能大赛财经赛道项目参考逐字稿五

我是网络安全兼技能大赛工程师,专注网络安全技术学习与技能大赛实战!持续分享最新的技术文章,帮你少走弯路,一起在技术赛道上进步~ 126

图解AVL树删除

AVL树删除节点的过程是,先找到该节点,然后进行删除。由于删除节点的位置不同,导致删除后节点进行移动的方式不同。删除节点的位置分为以下4类: 1.删除叶子结点。操作:直接删除,然后依次向上调整为AVL树。 2.删除非叶子节点,该节点只有左孩子。操作:该节点的值替换为左孩子节点的值,然后删除左孩子节点。【左孩子节点为叶子结点,所以删除左孩子节点的情况为第1种情况。】【为什么左孩子节点为叶子节点,...

Pinker_Q 1684

【知识分享】IBIS 建模指南 05

本文详细阐述了IBIS模型创建过程中的关键技术和数据规范要求。主要内容包括:1. 数据完整性检查要点,强调I-V和V-T数据必须覆盖所有工艺角且匹配;2. 数据限制处理方法,介绍100/1000点限制下的两种数据筛选算法;3. 特殊数据处理技术,包括内部终端电阻调整和V-T表时间窗口选择;4. 高级关键字应用,涵盖[ModelSelector]、[Sub model]、[DiffPin]等复杂功能实现方法;5. 预加重缓冲器等特殊结构的建模方案。

一只豌豆象的博客 1592

地平线J6的基础简介

地平线J6M芯片:面向中阶辅助驾驶市场的高性价比芯片

weixin_43084908的博客 4438

AVL 树:从递归到迭代,吃透平衡二叉树的插入与删除

本文详细解析了AVL树的核心原理与实现方法。首先通过BST退化为链表的例子说明AVL树的必要性,指出其通过平衡因子和旋转操作保持高效查询性能(O(logn))。文章系统讲解了AVL树的三个核心概念:平衡定义、关键术语和四种旋转操作,并提供了完整的C语言实现代码。 重点对比了递归版和迭代版实现,详细介绍了路径记录和平衡调整的实现方法 文章特别强调旋转操作的本质是让子节点当父节点,这一理解对后续学习红黑树等高级数据结构至关重要。

2501_93180375的博客 1227

华为OD机试 - 机器人活动区域(Java 双机位C卷 200分)

现有一个机器人,可放置于 M × N的网格中任意位置,每个网格包含一个非负整数编号。之后M行表示网格数值,每行N个数值(数值大小用k表示),数值间用单个空格分隔,行首行尾无多余空格。说明:图中绿色区域,相邻网格差值绝对值都小于等于1,且为最大区域,对应网格点数目为6。M、N、k均为整数,且1

学Java,找哪吒 915

平衡二叉树(AVL树)的查找,插入和删除

1,http://blog.youkuaiyun.com/zzuchengming/article/details/49824561这是我转载的一个讲解AVL树的文章,思路很好,内容也很清晰,这里基础知识不再赘述! 2,下边是我参考这篇文章写的代码,发现了其中的一个小错误! #include "stdafx.h" #include using std::cin; using std::cout; usi

记录每一个小阶段的学习心得,持之以恒! 1511

爆肝5万字❤️Open3D 点云数据处理基础(Python版)

本文为Open3D 点云数据处理基础教程(Python版),小白也能轻松上手!还等什么呢,学起来!

孙悟空 13万+

【MATLAB例程】三维下的IMM(交互式多模型),模型使用CV(匀速)和CA(匀加速),滤波使用EKF。附完整代码

CV模型:状态包含位置、速度和零加速度(9维状态),状态转移矩阵忽略加速度项CA模型:完整包含位置、速度和加速度(9维状态),状态转移矩阵包含二次项过程噪声矩阵Q分别根据两种模型的运动特性推导。

985工科博士毕业,专攻定位、导航和滤波等算法研究。从业10年,主要使用MATLAB 560

平衡二叉树(AVL)插入、删除详解——基于树的查找(二)

由上节内容二叉排序树可知: 二叉排序树在最好的情况下只需O(logn)的时间代价; 但在最差情况下会蜕化为线性查找的时间复杂度O(n); 造成原因:这种情况主要是由于二叉排序树中结点分布不均衡导致,可能是二叉排序树在建立时由于输入序列造成的,也可能是由于在树中不断插入结点而造成的。 解决想法:如果能够找到一种方法,使得二叉排序树不受输入序列或插入结点等的影响,...

weixin_39651041的博客 1965

【ArcGIS微课1000例】0068:ArcGIS加载world imagery高清卫星影像教程

本文介绍了如何在ArcGIS中加载World Imagery高清卫星影像作为谷歌影像的替代方案。通过添加ArcGIS Server并输入在线图集URL(https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer),即可连接并预览包含中国影像、青海湖、东方明珠等全球高清卫星图。该教程提供了详细的操作步骤图示,帮助用户快速获取优质底图数据,适用于地理信息分析和可视化应用。

智慧空间实验室 5414

一种基于平衡二叉树(AVL树)插入、查找和删除的简易图书管理系统

本文介绍了一种基于AVL树的插入、查找和删除操作的简易图书管理系统。重点分析了如何在插入和删除一颗AVL树中结点的同时,还能确保树的平衡性。借助文字和图片结合的形式,充分分析了各种情况。

This blog is a space to document my professional learnings, personal reflections, and everything in between. 5240

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C语言实现平衡二叉树的插入与删除

本文参考b站up,发布的视频教程数据结构-平衡二叉树(AVL)-C语言实现这个视频讲解通俗易懂,代码可读性也比较高,值得网友去学习。所以本文代码基于此视频教程作为参考,不过这里的代码但略有改动,程序的思路是相同的。数据结构系列19-平衡二叉树 | tyrantlucifer本文不讲大量空洞的理论。秉承以实践为主,理论为辅的宗旨讲解平衡二叉树的插入与删除的实现。前面第一节第二节主要是简述一些基本的概念,对编写程序的帮助有限,从第三节开始结合实际讲解程序的思路。

qq_21708039的博客 1473

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

平衡二叉树【AVL树】——插入、删除

1、平均查找长度(树高): 2、结点的平衡因子=左子树高-右子树高平衡二叉树结点的平衡因子只可能是0,1或-1 2、插入 2.1 每次调整的对象都是“最小不平衡子树” 2.2 调整最小不平衡子树A ①LL【A的左孩子右上旋】:在A的左孩子的左子树中插入导致不平衡 ②RR【A的右孩子左上旋】:在A的右孩子的右子树中插入导致不平衡 ③LR【A的左孩子的右孩子先左上旋再右上旋】:

yyy_zxc的博客 432

visio安装包

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

平衡二叉树(AVL树)C++代码实现

目录平衡二叉树定义AVLAVLAVL树类的封装AVLAVLAVL树的插入操作与平衡化LLLLLL型调整RRRRRR型调整LRLRLR型调整RLRLRL型调整AVLAVLAVL树查找操作AVLAVLAVL树删除结点操作总源代码 平衡二叉树定义 为了使二叉排序树的平均查找长度更小,需要适当控制树高,显然,控制树高的一个有效措施就是尽量保持树的左右子树高度大致平衡,由此产生了平衡二叉树的概念。 G.M.Adelson−VelskiiG.M.Adelson-VelskiiG.M.Adelson−Velskii和E.

RealCoder的博客 4221

【C++高阶】精通AVL树:全面剖析与深度学习

数据结构中AVL树的全面剖析与深度学习

You build it, you run it 2182

平衡二叉树(AVL树)

平衡二叉树(AVL树)

Xpccccc的博客 3068

二叉查找树,平衡二叉树(AVL树),红黑树

由于红黑树的广泛应用,所以面试中这几种树可能会被广泛提及,这里先简单总结一下,以后有需要可以再补充。 二叉查找树 没什么可说的。。。 平衡二叉树(AVL树) 定义 为避免二叉搜索树高度增长过快,规定在插入和删除节点时,要保证任意节点的左右子树高度差不超过1,这样的二叉搜索树就叫做平衡二叉搜索树。是一种自平衡的二叉搜索树,也叫AVL树,得名于它的发明者 G.M. Adelson-Velsky 和 E...

Blssel的博客 786

转载:什么是平衡二叉树(AVL)(+新增理解笔记)

转载:什么是平衡二叉树 什么是平衡二叉树(AVL) Wiki:在计算机科学中,AVL树是最早被发明的自平衡二叉查找树。在AVL树中,任一节点对应的两棵子树的最大高度差为1,因此它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下的时间复杂度都是{\displaystyle O(\log {n})}。增加和删除元素的操作则可能需要借由一次或多次树旋转,以实现树的重新平衡。AVL 树得名于它的发明者 G. M. Adelson-Velsky 和 Evgenii Landis,他们在1962年的论文《An a

kevin的博客 644
上一篇: 二叉排序树(搜索树)的建立、插入、查找、删除
下一篇: 堆的建立、插入、删除以及堆排序
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值