在讲解AVL树之前必须了解二叉搜索树,
可以看我之前的博客:二叉搜索树

AVL树是在二叉搜索树的基础上,在向二叉树排序树中插入新的结点,如果保证每个结点的左右子树的高度差的绝对值不超过1,即需要在插入的时候判断是否满足条件,然后对树进行旋转,从而可减低树的高度,减少平均搜索长度。

AVL树:(1)它的左右子树都是AVL树
(2)右子树和左子树的高度差(平衡因子)的绝对值不能超过1 (1 0 -1)。

给出实现AVL树的节点

template<class T>
struct BlancedBianryTreeNode
{BlancedBianryTreeNode(T data): _data(data), _bf(0), _pLeft(NULL), _pRight(NULL), _pParent(NULL){}T _data;int _bf; //平衡因子:右子树的高度-左子树的高度BlancedBianryTreeNode<T>* _pLeft;BlancedBianryTreeNode<T>* _pRight;BlancedBianryTreeNode<T>* _pParent;
};

下面讲解如何向平衡二叉树中插入一个元素, 大神勿喷。
步骤1:如果是空树,插入后即为根节点,插入后直接返回
步骤2:如果树不空,寻找插入位置,若在寻找的过程中找到key,则插入失败直接返回(注:与二叉搜索树的插入操作一样)
步骤3:插入结点,链接到树上,
步骤4:更新平衡因子
步骤5:对树进行调整:旋转

步骤2详解:在找的过程中,需要标记其找入插入位置的父节点pParent,因为在插入新节点pCur的时候,需要判断插入的位置(插入到父节点的左边还是右边)。直接看下面的代码

步骤4详解:插入新元素后该元素的平衡因子为0,但是其父节点的平衡因子可能改变,所以需要更新其平衡因子bf。
如果pCur为父节点pParent的左孩子,则pParent->_bf–;
如果pCur为父节点pParent的右孩子,则pParent->_bf++;
一直向上更新,直到更新到根节点或者父节点的bf为0。
如果父节点的bf为2或者-2的话,就不保持平衡,需要进行旋转。

步骤5详解 旋转有四种旋转方式:左旋,右旋,左右旋,右左旋
(1)左旋分为三种情况:

步骤一:先把SubRL链接到pParent上,更新SubRL的父节点,注意SubRL可能为空
步骤二:修改subR,挂到原子树上,注意先得保存pParent的父节点,注意pParent可能为根节点,其父节点为NULL
步骤三:修改pParent,挂接到subR上
步骤四:更新pParent和SubR的平衡因子
从图中可以看出:三种方式的左旋后pParent和SubR的平衡因子都为0。所以旋转后,再更新pParent和SubR的平衡因子。
什么时候左旋:pParent->bf 为2 ,SubR->bf 为1。
代码

    void _RotateL(Node* pParent) //左旋{Node* SubR = pParent->_pRight; //当前节点pParent的左孩子Node* SubRL = SubR->_pLeft; //可能为空//先将 SubRL 链接到pParent->_pRight = SubRL;if (SubRL) //第三种情况{SubRL->_pParent = pParent;}//修改SubRNode *pPparent = pParent->_pParent;  //pParent可能为根节点SubR->_pParent = pPparent; //修改SubR的父节点//把SubR链接到原子树上if (pPparent == NULL)//可能为根节点{_pRoot = SubR;}else{if (pParent == pPparent->_pLeft) pPparent->_pLeft = SubR;elsepPparent->_pRight = SubR;}//修改pParent,SubR->_pLeft = pParent;pParent->_pParent = SubR;//更新SubR和pParent的平衡因子SubR->_bf = pParent->_bf = 0;}

(2)右旋:和左旋相似

直接贴代码:步骤和左旋类似
什么时候左旋:pParent->bf 为-2 ,SubL->bf 为-1

void _RotateR(Node* pParent) //右旋{Node* SubL = pParent->_pLeft;Node* SubLR = SubL->_pRight; //可能为第三种情况//修改SubLRpParent->_pLeft = SubLR;if (SubLR){SubLR->_pParent = pParent;}//修改subLNode* pPparent = pParent->_pParent;SubL->_pParent = pPparent;//subL链接到原子树上if (pPparent == NULL)_pRoot = SubL;else{if (pPparent->_pLeft == pParent)pPparent->_pLeft = SubL;elsepPparent->_pRight = SubL;}//修改pparentSubL->_pRight = pParent;pParent->_pParent = SubL;//更新subl和pparent的平衡因子SubL->_bf = pParent->_bf = 0;}

(3)左右旋:先进行左旋,再进行右旋

分析每种情况的pParent和SubL和SubLR的平衡因子,
找到规律,当未更新subLR->bf = -1时,
pParent->bf = 1; SubL->bf = 0;
当未更新subLR->bf = 1时,pParent->bf = 0; SubL->bf = -1;
**左右旋的时机:**pParent->bf 为-2 ,SubR->bf 为1

    void _RotateLR(Node* pParent) //左右旋 分三种{//根据 subLR的平衡因子:int bs = pParent->_pLeft->_pRight->_bf;Node* SubL = pParent->_pLeft;_RotateL(pParent->_pLeft);_RotateR(pParent);if (bs == 1){pParent->_bf = 0;SubL->_bf = -1;}else if (bs == -1){pParent->_bf = 1;SubL->_bf = 0;}

(4)右左旋:与左右旋类似,

分析每种情况的pParent和SubR和SubRL的平衡因子,与左旋旋正好相反
找到规律,当未更新subRL->bf = -1时,
pParent->bf = 0; SubR->bf = 1;
当未更新subRL->bf = 1时,pParent->bf = -1; SubR->bf = 0;
右左旋时机:pParent->bf 为2 ,SubR->bf 为-1

void _RotateRL(Node* pParent) //右左旋转{int bs = pParent->_pRight->_pLeft->_bf;Node* SubR = pParent->_pRight;_RotateR(pParent->_pRight);_RotateL(pParent);if (bs == 1){pParent->_bf = -1;SubR->_bf = 0;}else if (bs == -1){pParent->_bf = 0;SubR->_bf = 1;}}

插入操作的整体代码:

bool Insert(T data){if (_pRoot == NULL){_pRoot = new Node(data);return true;}Node* pCur = _pRoot;Node* pParent = NULL;while (pCur){if (data < pCur->_data){pParent = pCur;pCur = pCur->_pLeft;}else if (data > pCur->_data){pParent = pCur;pCur = pCur->_pRight;}elsereturn false;}//找到插入节点,pCur = new Node(data);pCur->_pParent = pParent;if (data > pParent->_data)pParent->_pRight = pCur;elsepParent->_pLeft = pCur;//更新平衡因子while (pParent){if (pCur == pParent->_pLeft)pParent->_bf--;         elsepParent->_bf++;//平衡因子改变if (pParent->_bf == 0)return true;else if (pParent->_bf <-1 || pParent->_bf > 1)break;else{pCur = pParent;pParent = pCur->_pParent;}           }//跳出循环 pParent的因子可能为2 或者 -2 则进行旋转//旋转//可能pParent为空,不需要进行旋转if (pParent){if (pParent->_bf == 2){if (pCur->_bf == 1)//进行左旋_RotateL(pParent);else_RotateRL(pParent);}else if (pParent->_bf == -2){if (pCur->_bf == -1)_RotateR(pParent);else_RotateLR(pParent);}}   return true;}

如果有错误,欢迎大家指出来。

【AVL树】AVL树的插入操作以及旋转相关推荐

  1. 数据结构--Avl树的创建,插入的递归版本和非递归版本,删除等操作

    AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树. 2.带有平衡条件:每个结点的左右子树的高度之差的绝对值最多为1(空树的高度为-1). 也就是说,AVL树,本质上是带了平 ...

  2. AVL树C++实现(插入,删除,查找,清空,遍历操作)

    AVL.h文件代码 #pragma once #include<iostream> #include<stack>#include <assert.h> using ...

  3. AVL树、splay树(伸展树)和红黑树比较

    AVL树.splay树(伸展树)和红黑树比较 一.AVL树: 优点:查找.插入和删除,最坏复杂度均为O(logN).实现操作简单 如过是随机插入或者删除,其理论上可以得到O(logN)的复杂度,但是实 ...

  4. 种树:二叉树、二叉搜索树、AVL树、红黑树、哈夫曼树、B树、树与森林

    虽然今天不是植树节,但是我今天想种树. 文章目录 树,什么是树? 二叉树 定义 二叉树的创建 二叉树的前中后序遍历 前序遍历: 中序遍历 后序遍历 已知前序.中序遍历结果,还原二叉树 已知后序.中序遍 ...

  5. 浅析AVL树--AVL树的双旋转

    浅析AVL树–AVL树的双旋转 接上篇博文:浅析AVL树–AVL树的概念及单旋转 AVL树如何恢复平衡之双旋转 首先假设我们有一颗已经处于平衡的AVL树: 上篇博文已经解决了LL和RR两种情况的平衡恢 ...

  6. 红黑树原理学习以234树来学习(1)插入操作

    ** 前言: 234树在大部分的程序语言中实现比较困难,所以等价的用红黑树来实现. 核心思想:红黑树的红色节点上移到父亲节点就变成了一颗234树. 一:红黑树与234树的等价关系如下: 一个234树可 ...

  7. B树--B+树原理及操作(插入,删除)

    前言: B树代码戳这里:https://blog.csdn.net/alzzw/article/details/97663352     在讲B树之前,先说一下多路查找树: 2-3树:是一种多路查找树 ...

  8. Algorithm:树相关算法(BBT/BST/B树/R树)简介(二叉查找树、二叉查找树的插入节点、二叉查找树的删除、二叉树的遍历、平衡二叉树)C 语言实现

    Algorithm:树相关算法(BBT/BST/B树/R树)简介(二叉查找树.二叉查找树的插入节点.二叉查找树的删除.二叉树的遍历.平衡二叉树)C++语言实现 目录 树的基础知识 1.二叉树的遍-前序 ...

  9. (王道408考研数据结构)第七章查找-第三节:B树(基本概念及其操作)

    文章目录 一:B树的基本概念 (1)B树 (2)B树(假设 m m m阶)特点及效率 二:B树操作 (1)插入 (2)查找 (3)删除 一:B树的基本概念 (1)B树 B树(B-tree)

最新文章

  1. CentOS修改忘记密码
  2. jQuery筛选器常用总结
  3. JAVA数组及数组的应用
  4. Entity Framework Core 命名约定
  5. numpy的基本使用 附python代码详细讲解(numpy函数,创建数组,常用属性,索引切片,数组的复制,修改维度,数组的分割、拼接、转置)
  6. Angular通过CORS实现跨域方案
  7. 获取URL各项参数(Java)
  8. LayoutInflater
  9. A little knowledge point every day,一起学python
  10. user reg.php,织梦member/reg_new.php SQL注入漏洞修复
  11. 案例|高稳定紫外LED光源助力流体力学PSP技术
  12. 系统集成项目管理工程师 下午 真题 及考点(2022年四套卷)
  13. 【幻化万千戏红尘】qianfengDay04-java基础学习:for语句.while语句,do-while语句
  14. 使用PHPstudy在Windows服务器下部署PHP系统
  15. 计算机在职博士好毕业么,北京大学计算机在职博士生毕业以后学历会提升么
  16. BugkuCTF web18_秋名山车神 writeup
  17. 单反数码相机(百科名片)
  18. 银河麒麟v4.0.2安装
  19. 用计算机求函数公式,计算机函数
  20. Gazebo-Ros搭建小车和场景并运行slam算法进行建图0--整体描述和资源

热门文章

  1. 大学生入学必备:计算机科学与技术专业相关信息,一文让你全了解!
  2. 知识图谱构建:py2neo的实体关系以及节点显示图片
  3. 王道数据结构2.2.4——1、设计递归算法删除不带头结点的单链表L中所有值为x的结点
  4. Edge浏览器崩溃,错误代码: STATUS_STACK_BUFFER_OVERRUN
  5. windows安装vcpkg过程下载失败问题的解决方法
  6. java服务器保存特殊字符和表情入库报错
  7. 10年测试经验分享:新手怎么找软件测试的项目?
  8. 心电图心跳信号多分类预测-建模调参(四)
  9. 转载 gro转lammps
  10. Oracle中实现分页