我的编程空间,编程开发者的网络收藏夹
学习永远不晚

AVL树数据结构输入与输出怎么实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

AVL树数据结构输入与输出怎么实现

本篇内容介绍了“AVL树数据结构输入与输出怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

    AVL树(平衡二叉树):

    AVL树本质上是一颗二叉查找树,但是它又具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为平衡二叉树。下面是平衡二叉树和非平衡二叉树对比的例图:

    AVL树数据结构输入与输出怎么实现

    平衡因子(bf):结点的左子树的深度减去右子树的深度,那么显然-1<=bf<=1;

    AVL树的作用:

    我们知道,对于一般的二叉搜索树(Binary Search Tree),其期望高度(即为一棵平衡树时)为log2n,其各操作的时间复杂度(O(log2n))同时也由此而决定。但是,在某些极端的情况下(如在插入的序列是有序的时),二叉搜索树将退化成近似链或链,此时,其操作的时间复杂度将退化成线性的,即O(n)。我们可以通过随机化建立二叉搜索树来尽量的避免这种情况,但是在进行了多次的操作之后,由于在删除时,我们总是选择将待删除节点的后继代替它本身,这样就会造成总是右边的节点数目减少,以至于树向左偏沉。这同时也会造成树的平衡性受到破坏,提高它的操作的时间复杂度。

    例如:我们按顺序将一组数据1,2,3,4,5,6分别插入到一颗空二叉查找树和AVL树中,插入的结果如下图:

    AVL树数据结构输入与输出怎么实现

    AVL树数据结构输入与输出怎么实现

    由上图可知,同样的结点,由于插入方式不同导致树的高度也有所不同。特别是在带插入结点个数很多且正序的情况下,会导致二叉树的高度是O(N),而AVL树就不会出现这种情况,树的高度始终是O(lgN).高度越小,对树的一些基本操作的时间复杂度就会越小。这也就是我们引入AVL树的原因

    AVL树的基本操作:

    AVL树的操作基本和二叉查找树一样,这里我们关注的是两个变化很大的操作:插入和删除!

    我们知道,AVL树不仅是一颗二叉查找树,它还有其他的性质。如果我们按照一般的二叉查找树的插入方式可能会破坏AVL树的平衡性。同理,在删除的时候也有可能会破坏树的平衡性,所以我们要做一些特殊的处理,包括:单旋转和双旋转!

    AVL树的插入,单旋转的第一种情况---右旋:

    AVL树数据结构输入与输出怎么实现

    由上图可知:在插入之前树是一颗AVL树,而插入之后结点T的左右子树高度差的绝对值不再 < 1,此时AVL树的平衡性被破坏,我们要对其进行旋转。由上图可知我们是在结点T的左结点的左子树上做了插入元素的操作,我们称这种情况为左左情况,我们应该进行右旋转(只需旋转一次,故是单旋转)。具体旋转步骤是:

    T向右旋转成为L的右结点,同时,Y放到T的左孩子上。这样即可得到一颗新的AVL树,旋转过程图如下:

    AVL树数据结构输入与输出怎么实现

    左左情况的右旋举例:

    AVL树数据结构输入与输出怎么实现

    AVL树的插入,单旋转的第二种情况---左旋:

    AVL树数据结构输入与输出怎么实现

    由上图可知:在插入之前树是一颗AVL树,而插入之后结点T的左右子树高度差的绝对值不再 < 1,此时AVL树的平衡性被破坏,我们要对其进行旋转。由上图可知我们是在结点T的右结点的右子树上做了插入元素的操作,我们称这种情况为右右情况,我们应该进行左旋转(只需旋转一次,故事单旋转)。具体旋转步骤是:

    T向右旋转成为R的左结点,同时,Y放到T的左孩子上。这样即可得到一颗新的AVL树,旋转过程图如下:

    AVL树数据结构输入与输出怎么实现

    右右情况的左旋举例:

    AVL树数据结构输入与输出怎么实现

    以上就是插入操作时的单旋转情况!我们要注意的是:谁是T谁是L,谁是R还有谁是X,Y,Z!T始终是开始不平衡的左右子树的根节点。显然L是T的左结点,R是T的右节点。X、Y、Y是子树当然也可以为NULL.NULL归NULL,但不能破坏插入时我上面所说的左左情况或者右右情况。

    AVL树的插入,双旋转的第一种情况---左右(先左后右)旋:

    AVL树数据结构输入与输出怎么实现

    由上图可知,我们在T结点的左结点的右子树上插入一个元素时,会使得根为T的树的左右子树高度差的绝对值不再 < 1,如果只是进行简单的右旋,得到的树仍然是不平衡的。我们应该按照如下图所示进行二次旋转:

    AVL树数据结构输入与输出怎么实现

    左右情况的左右旋转实例:

    AVL树数据结构输入与输出怎么实现

    AVL树的插入,双旋转的第二种情况---右左(先右后左)旋:

    AVL树数据结构输入与输出怎么实现

    由上图可知,我们在T结点的右结点的左子树上插入一个元素时,会使得根为T的树的左右子树高度差的绝对值不再 < 1,如果只是进行简单的左旋,得到的树仍然是不平衡的。我们应该按照如下图所示进行二次旋转:

    AVL树数据结构输入与输出怎么实现

    右左情况的右左旋转实例:

    AVL树数据结构输入与输出怎么实现

    AVL树的插入代码实现:(仅供参考)

    懂了以上单旋转和双旋转的原理之后,那么代码写起来也就比较简单了,以下是我写的代码,如果有错还望大家不吝指正。(参考数据结构与算法分析)

    #include <iostream>using namespace std;#define DataType inttypedef struct AvlNode{    DataType    data;    AvlNode    * m_pLeft;    AvlNode    * m_pRight;    int height;}*AvlTree,*Position,AvlNode;//求两个数的最大值int Max(int a,int b){    return a>b?a:b;}//求树的高度int Height( AvlTree T){    if(NULL == T)        return -1;    else        return T->height;}//单旋转右旋AvlTree singleRotateWithRight(AvlTree T){    AvlTree L = T->m_pLeft;    T->m_pLeft = L->m_pRight;    L->m_pRight = T;    T->height = Max( Height(T->m_pLeft),Height(T->m_pRight) ) + 1;    L->height = Max( Height(L->m_pLeft),Height(L->m_pRight) ) + 1;    return L;    //此时L成为根节点了(可参考AVL的插入的左左情况的右旋图)}//单旋转左旋AvlTree singleRotateWithLeft(AvlTree T){    AvlTree R = T->m_pRight;    T->m_pRight = R->m_pLeft;    R->m_pLeft = T;    T->height = Max( Height(T->m_pLeft),Height(T->m_pRight) ) + 1;    R->height = Max( Height(R->m_pLeft),Height(R->m_pRight) ) + 1;    return R;    //此时R成为根节点了(可参考AVL的插入的左左情况的左旋图)}//双旋转,先左后右AvlTree doubleRotateWithLeft(AvlTree T)        //先左后右{    T->m_pLeft = singleRotateWithLeft(T->m_pLeft);    return singleRotateWithRight(T);}//双旋转,先右后左AvlTree doubleRotateWithRight(AvlTree T)    //先右后左{    T->m_pRight = singleRotateWithRight(T->m_pRight);    return singleRotateWithLeft(T);}AvlTree AvlTreeInsert(AvlTree T, DataType x){    if(T == NULL)    //如果树为空    {        T = (AvlNode *)malloc(sizeof(struct AvlNode));        if(T)        {            T->data = x;            T->m_pLeft    = NULL;            T->m_pRight = NULL;            T->height = 0;        }        else        {            cout << "空间不够" << endl;            exit(0);        }    }    else if( x < T->data)        //如果插入到T结点的左子树上    {        T->m_pLeft = AvlTreeInsert(T->m_pLeft,x);    //先插入,后旋转        if(Height(T->m_pLeft) - Height(T->m_pRight) == 2) //只有可能是这个        {            if(x < T->m_pLeft->data)        //左左情况,只需要右旋转            {                T = singleRotateWithRight( T );            }            else                            //左右情况,双旋转,先左            {                T = doubleRotateWithLeft( T );            }        }    }    else if( x > T->data )    {        T->m_pRight = AvlTreeInsert(T->m_pRight,x);        if(Height(T->m_pRight) - Height(T->m_pLeft) == 2)        {            if(x > T->m_pRight->data)        //右右情况,进行左旋            {                T = singleRotateWithLeft( T );            }            else                            //左右情况,双旋转,先右            {                T = doubleRotateWithRight( T );            }        }    }    //如果这个数已经存在,那么不进行插入    T->height = Max(Height(T->m_pLeft),Height(T->m_pRight)) + 1;    return T;}//递归实现中序遍历void inOrderVisitUseRecur(const AvlTree pCurrent){    if(pCurrent)    {        inOrderVisitUseRecur(pCurrent->m_pLeft);        cout << pCurrent->data << " ";        if(pCurrent->m_pLeft)            cout << " leftChild: "<<pCurrent->m_pLeft->data;        else            cout << " leftChild: "<<"NULL" ;        if(pCurrent->m_pRight)            cout << " rightChild: "<<pCurrent->m_pRight->data;        else            cout << " rightChild: "<< "NULL";        cout << endl;        inOrderVisitUseRecur(pCurrent->m_pRight);    }}int main(){    AvlTree root = NULL;    root = AvlTreeInsert(root,1);    root = AvlTreeInsert(root,2);    root = AvlTreeInsert(root,3);    root = AvlTreeInsert(root,4);    root = AvlTreeInsert(root,5);    root = AvlTreeInsert(root,6);    root = AvlTreeInsert(root,7);    root = AvlTreeInsert(root,8);    root = AvlTreeInsert(root,9);    root = AvlTreeInsert(root,10);    root = AvlTreeInsert(root,11);    root = AvlTreeInsert(root,12);    root = AvlTreeInsert(root,13);    root = AvlTreeInsert(root,14);    root = AvlTreeInsert(root,15);    inOrderVisitUseRecur(root);    return 0;}

    “AVL树数据结构输入与输出怎么实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    AVL树数据结构输入与输出怎么实现

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    AVL树数据结构输入与输出怎么实现

    本篇内容介绍了“AVL树数据结构输入与输出怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!AVL树(平衡二叉树):AVL树本质上是一颗
    2023-06-30

    java怎么实现数据的输入和输出

    在Java中,可以使用Scanner类来实现数据的输入和使用System.out.println()方法来实现数据的输出。以下是一个简单的示例代码,演示了如何使用Scanner类实现数据的输入和使用System.out.println()
    2023-10-27

    C语言怎么实现数据输入和输出

    本文小编为大家详细介绍“C语言怎么实现数据输入和输出”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言怎么实现数据输入和输出”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。语句C语言的语句用来向计算机系统发出操
    2023-07-02

    c++输入数据后怎么得出结果

    c++kquote>从 c++ 程序中输入数据并得到结果需要以下步骤:1. 定义变量;2. 使用 cin 获取用户输入;3. 处理输入数据;4. 使用 cout 显示结果。例如,计算矩形面积时,需要定义 length 和 width 变量,
    c++输入数据后怎么得出结果
    2024-04-22

    php页面左右输出数据怎么实现

    在 PHP 中,可以使用 echo 函数来输出数据到页面上。以下是一个简单的示例,演示如何在页面左右两边输出数据:
    php页面左右输出数据怎么实现
    2024-03-02

    怎么用C语言代码实现复数的加减及输出结构体

    这篇“怎么用C语言代码实现复数的加减及输出结构体”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么用C语言代码实现复数的加减
    2023-06-29

    PHP数据结构:序列化与反序列化的艺术,实现数据持久化与传输

    在 php 中,序列化将数据结构转换为字符串,而反序列化将字符串还原为数据结构,实现数据的持久化和传输。序列化函数 serialize 将数据结构转换为字符串,而 unserialize 函数从字符串中还原序列化后的数据。序列化可用于数据持
    PHP数据结构:序列化与反序列化的艺术,实现数据持久化与传输
    2024-05-14

    C#数据结构与队列怎么实现

    这篇文章主要讲解了“C#数据结构与队列怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#数据结构与队列怎么实现”吧!C#数据结构与算法之队列是一种特殊的线性表,它只允许在表的前端(f
    2023-06-18

    Java数据结构之线索化二叉树怎么实现

    这篇文章主要介绍“Java数据结构之线索化二叉树怎么实现”,在日常操作中,相信很多人在Java数据结构之线索化二叉树怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java数据结构之线索化二叉树怎么实现
    2023-06-30

    C++高级数据结构之二叉查找树怎么实现

    本文小编为大家详细介绍“C++高级数据结构之二叉查找树怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“C++高级数据结构之二叉查找树怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。高级数据结构(Ⅳ)
    2023-06-30

    Java数据结构之插入排序与希尔排序怎么实现

    这篇文章主要介绍“Java数据结构之插入排序与希尔排序怎么实现”,在日常操作中,相信很多人在Java数据结构之插入排序与希尔排序怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java数据结构之插入排序
    2023-07-05

    C语言怎么实现输入两个数字将其按从小到大输出的方法

    这篇文章给大家分享的是有关C语言怎么实现输入两个数字将其按从小到大输出的方法的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。代码实例:1.第一种方法(if)#include int main(){
    2023-06-14

    Java怎么通过注解实现接口输出时数据脱敏

    小编给大家分享一下Java怎么通过注解实现接口输出时数据脱敏,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Java注解实现接口输出数据脱敏在后台管理中,对于手机号
    2023-06-22

    Python数据结构与算法中的栈怎么实现

    这篇文章主要介绍“Python数据结构与算法中的栈怎么实现”,在日常操作中,相信很多人在Python数据结构与算法中的栈怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python数据结构与算法中的栈怎
    2023-06-29

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录