1、什么是平衡二叉树

平衡因子(Balance Factor)

简称BF:BF(T) = h(l) - h(r),其中 h(l)和 h(r)分别是T的左、右子树的高度。

平衡二叉树(Balance Binary Tree)(AVL树)

空树,或者任一节点左、右子树的高度绝对值不超过1,|BF(T)|<=1。本质是一颗改进后的二叉搜索树。

2、平衡二叉树的调整

RR旋转

RR旋转代码实现:

 //必须要有一个右节点//将A和B做右单旋,且更新A和B的树高度//返回新的根节点Bprivate AVLNode singleRightRotation(AVLNode A) {AVLNode B = A.right;A.right = B.left;B.left = A;A.height = Math.max(getHeight(A.left),getHeight(A.right))+1;B.height = Math.max(getHeight(B.right),A.height)+1;return B;}

LL旋转

LL旋转代码实现:

 private AVLNode singleLeftRotation(AVLNode A) {AVLNode B = A.left;A.left=B.right;B.right=A;A.height = Math.max(getHeight(A.left),getHeight(A.right))+1;B.height = Math.max(getHeight(B.left),A.height)+1;return B;}

LR旋转

LR旋转代码实现:

 //A必须有一个左节点B,而B必须有一个右节点C//A、B分别和C做两次单旋,返回新的根节点Cprivate AVLNode DoubleLeftRightRotation(AVLNode A) {//B和C做单右旋,返回根节点CA.left = singleRightRotation(A.left);//A和C做但左旋,返回根节点Creturn singleLeftRotation(A);}

RL旋转

RL旋转代码实现:

 public AVLNode DoubleRightLeftRotation(AVLNode A) {A.right = singleLeftRotation(A.right);return singleRightRotation(A);}

3、平衡二叉树的插入节点

平衡二叉树的插入和二叉搜索树的插入区别?
相同点:都是从根节点开始判断,通过递归方式往下判断,直至找到插入位置然后插入节点。
不同点:根据平衡二叉树定义,平衡因子不能超过1,所以对于插入后的平衡二叉树需要判断是否需要平衡调整。判断时机是在递归结束返回的过程中,判断当前节点的平衡因子绝对值是否等于2,如果是的话,做平衡调整。最后跟新当前节点的树高度。(从树的叶子节点开始一直往上判断、调整直至平衡)

插入代码实现:

public AVLNode insert(AVLNode node,int value) {if (node==null) {node = new AVLNode(value);}else {if (value<node.value) {node.left = insert(node.left, value);if(getHeight(node.left)-getHeight(node.right)==2) {if (value<node.left.value) {node = singleLeftRotation(node);}else if (value>node.left.value) {node = DoubleLeftRightRotation(node);}}}else if (value>node.value) {node.right = insert(node.right, value);if (getHeight(node.left) - getHeight(node.right) == -2) {if (value > node.right.value) {node = singleRightRotation(node);} else if (value < node.right.value) {node = DoubleRightLeftRotation(node);}}}//跟新当前节点树高度updateHeight(node);}return node;}

4、平衡二叉树的删除节点

1、删除节点
平衡二叉树删除节点存在三种情况

  1. 删除的节点为叶子节点
  2. 删除的节点只存在左子树或者只存在右子树
  3. 删除的节点同时存在左子树和右子树

2、在递归返回过程中做平衡调整

删除节点代码实现:

  private AVLNode delete(int value) {//删除节点return delete(this, value);}

删除节点代码

 /*** 递归查找后删除节点,并且在递归返回过程中做平衡调整* @param node* @param value* @return*/private AVLNode delete(AVLNode node,int value) {if (node.value == value) {node = removeNode(node);}else {if (value < node.value) {node.left = delete(node.left, value);//实际上删除左子树上节点导致不平衡只有两种情况‘// 1、删除后当前节点要单右旋//2、删除后当前节点要左右旋if (getHeight(node.left) - getHeight(node.right) == -2) {if (node.right.left == null) {node = singleRightRotation(node);} else {node = DoubleRightLeftRotation(node);}}} else if (value > node.value) {node.right = delete(node.right, value);//同理可以推断出if (getHeight(node.left) - getHeight(node.right) == 2) {if (node.left.right == null) {node = singleLeftRotation(node);} else {node = DoubleLeftRightRotation(node);}}}updateHeight(node);}return node;}/*** 节点删除的三种情况* @param node* @return*/private AVLNode removeNode(AVLNode node) {//删除的节点为叶子节点if (node.left==null && node.right==null) {node =null;} else if (node.left==null || node.right==null){ //删除的节点只有左子树或者是右子树if (node.left==null) {node = node.right;}else {node = node.left;}} else { //删除的节点既有左子树又有右子树(需要获取左子树的最大节点或者右子树的最小节点替换)/*** 1、此处获取左子树最大节点的父节点* 2、获取父节点的右节点* 3、如果没有右节点,那么取父节点未左子树最大节点*/AVLNode leftChrildMaxParent = getLeftChrildMax(node.left);AVLNode leftChrildMax = leftChrildMaxParent.right;if (leftChrildMax == null) {leftChrildMax = leftChrildMaxParent;leftChrildMax.right = node.right;}else {leftChrildMax.left = node.left;leftChrildMax.right = node.right;leftChrildMaxParent.right = null;}node = leftChrildMax;}return node;}private AVLNode getLeftChrildMax(AVLNode node) {if (node==null) {return null;}AVLNode parentNode = node;AVLNode chrildNode = parentNode.right;while (chrildNode!=null) {if (chrildNode.right!=null) {parentNode = chrildNode;chrildNode = chrildNode.right;}else {break;}}return parentNode;}

平衡二叉树调整方法

  /*** 平衡二叉树调整方法* @param node* @return*/private AVLNode reviseNode(AVLNode node) {if (node==null) {return null;}else {node.left = reviseNode(node.left);node.right = reviseNode(node.right);if(getHeight(node.left)-getHeight(node.right)==2) {if (node.left.right==null) {node = singleLeftRotation(node);}else  {node = DoubleLeftRightRotation(node);}}else if (getHeight(node.left)-getHeight(node.right)==-2) {if (node.right.left==null) {node = singleRightRotation(node);}else {node = DoubleRightLeftRotation(node);}}updateHeight(node);return node;}}

5、 平衡二叉树全部代码

/*** 平衡二叉树实现*/
public class AVLNode {private AVLNode left;private AVLNode right;private Integer value;private int height;public AVLNode() {}public AVLNode(Integer value) {this(value,null,null,0);}public AVLNode(AVLNode node) {this.value = node.value;this.left = node.left;this.right = node.right;this.height = node.height;}public AVLNode(Integer value,AVLNode left,AVLNode right,int height) {this.value = value;this.left = left;this.right = right;this.height = height;}public AVLNode insert(AVLNode node,int value) {if (node==null) {node = new AVLNode(value);}else {if (value<node.value) {node.left = insert(node.left, value);if(getHeight(node.left)-getHeight(node.right)==2) {if (value<node.left.value) {node = singleLeftRotation(node);}else if (value>node.left.value) {node = DoubleLeftRightRotation(node);}}}else if (value>node.value) {node.right = insert(node.right, value);if (getHeight(node.left) - getHeight(node.right) == -2) {if (value > node.right.value) {node = singleRightRotation(node);} else if (value < node.right.value) {node = DoubleRightLeftRotation(node);}}}updateHeight(node);}return node;}public AVLNode find(int value) {if (this == null) return null;AVLNode node = this;while (node!=null) {if (node.value == value) {return node;}else if (value<node.value) {node = node.left;}else {node = node.right;}}return node;}private AVLNode delete(int value) {return delete(this, value);}/*** 递归查找后删除节点* @param node* @param value* @return*/private AVLNode delete(AVLNode node,int value) {if (node.value == value) {node = removeNode(node);}else {if (value < node.value) {node.left = delete(node.left, value);//实际上删除左子树上节点导致不平衡只有两种情况‘// 1、删除后当前节点要单右旋//2、删除后当前节点要左右旋if (getHeight(node.left) - getHeight(node.right) == -2) {if (node.right.left == null) {node = singleRightRotation(node);} else {node = DoubleRightLeftRotation(node);}}} else if (value > node.value) {node.right = delete(node.right, value);if (getHeight(node.left) - getHeight(node.right) == 2) {if (node.left.right == null) {node = singleLeftRotation(node);} else {node = DoubleLeftRightRotation(node);}}}updateHeight(node);}return node;}/*** 节点删除* @param node* @return*/private AVLNode removeNode(AVLNode node) {//删除的节点为叶子节点if (node.left==null && node.right==null) {node =null;} else if (node.left==null || node.right==null){ //删除的节点只有左子树或者是右子树if (node.left==null) {node = node.right;}else {node = node.left;}} else { //删除的节点既有左子树又有右子树(需要获取左子树的最大节点或者右子树的最小节点替换)/*** 1、获取左子树最大节点的父节点* 2、获取父节点的右节点* 3、如果没有右节点,那么取父节点未左子树最大节点*/AVLNode leftChrildMaxParent = getLeftChrildMax(node.left);AVLNode leftChrildMax = leftChrildMaxParent.right;if (leftChrildMax == null) {leftChrildMax = leftChrildMaxParent;leftChrildMax.right = node.right;}else {leftChrildMax.left = node.left;leftChrildMax.right = node.right;leftChrildMaxParent.right = null;}node = leftChrildMax;}return node;}private AVLNode getLeftChrildMax(AVLNode node) {if (node==null) {return null;}AVLNode parentNode = node;AVLNode chrildNode = parentNode.right;while (chrildNode!=null) {if (chrildNode.right!=null) {parentNode = chrildNode;chrildNode = chrildNode.right;}else {break;}}return parentNode;}/*** 平衡二叉树调整方法* @param node* @return*/private AVLNode reviseNode(AVLNode node) {if (node==null) {return null;}else {node.left = reviseNode(node.left);node.right = reviseNode(node.right);if(getHeight(node.left)-getHeight(node.right)==2) {if (node.left.right==null) {node = singleLeftRotation(node);}else  {node = DoubleLeftRightRotation(node);}}else if (getHeight(node.left)-getHeight(node.right)==-2) {if (node.right.left==null) {node = singleRightRotation(node);}else {node = DoubleRightLeftRotation(node);}}updateHeight(node);return node;}}private AVLNode DoubleLeftRightRotation(AVLNode A) {A.left = singleRightRotation(A.left);return singleLeftRotation(A);}public AVLNode DoubleRightLeftRotation(AVLNode A) {A.right = singleLeftRotation(A.right);return singleRightRotation(A);}private AVLNode singleLeftRotation(AVLNode A) {AVLNode B = A.left;A.left=B.right;B.right=A;A.height = Math.max(getHeight(A.left),getHeight(A.right))+1;B.height = Math.max(getHeight(B.left),A.height)+1;return B;}private AVLNode singleRightRotation(AVLNode A) {AVLNode B = A.right;A.right = B.left;B.left = A;A.height = Math.max(getHeight(A.left),getHeight(A.right))+1;B.height = Math.max(getHeight(B.right),A.height)+1;return B;}/*** 前序遍历* @return*/public void toString(AVLNode node) {if (node==null) {return ;}System.out.print(node.value+" ");toString(node.left);toString(node.right);}private int getHeight(AVLNode node) {if(node==null) {return -1;}else {int leftH = getHeight(node.left);int rightH = getHeight(node.right);return Math.max(leftH,rightH)+1;}}private void updateHeight(AVLNode node) {node.height = getHeight(node);}
}

平衡二叉树(Java实现)相关推荐

  1. 平衡二叉树(Java) -- 左旋旋右旋旋

    平衡二叉树 平衡二叉树(Java) -- 左旋旋右旋旋 平衡二叉树 -- 代码 平衡二叉树(Java) – 左旋旋右旋旋   平衡二叉树全称平衡二叉搜索树,所以首先具备了二叉搜索树的特性,因为二叉搜索 ...

  2. leetcode-110:判断平衡二叉树 Java

    Balanced Binary Tree Given a binary tree, determine if it is height-balanced. For this problem, a he ...

  3. 2021年备战面试--算法13

    public static void main(String[] args) {          System.out.println(getMax(query)); 0. 时间复杂度:JAVA数据 ...

  4. LeetCode855:考场就座

    如题: 思路分析: 我们每次挑选座位的时候,需要里最近的人距离最大,也就是说如果要坐在两个人之间,应该坐在中点的位置 因此我们可以将两个座位抽象成一个线段,第一个人是线段开始位置start,第二个人是 ...

  5. java TreeMap 源代码分析 平衡二叉树

    TreeMap 的实现就是红黑树数据结构,也就说是一棵自平衡的排序二叉树,这样就可以保证当需要快速检索指定节点. TreeSet 和 TreeMap 的关系 为了让大家了解 TreeMap 和 Tre ...

  6. java实现平衡二叉树(详细分析)

    package com.utils; import java.util.Iterator; import java.util.NoSuchElementException; /*** 平衡二叉树* 定 ...

  7. 高度平衡二叉树的构建_平衡二叉树建立及其增删改查(JAVA)

    平衡二叉树:指的是左右子树高度差的绝对值不超过一的二叉排序树. 主要思路:1.用左高度跟右高度代替平衡因子,大于1进行L~调整,小于-1进行R~调整 2.每次插入都通过递归计算一次各结点高度,然后进行 ...

  8. 映射表map(平衡二叉树实现)_手动实现Java集合容器之TreeMap(上)

    上一篇我们手写了HashMap,还有一个很重要的Map的实现类TreeMap.打开源码第一句话:* A Red-Black tree based {@link NavigableMap} implem ...

  9. avl二叉树 java_平衡二叉树之AVL树(Adelson-Velsky and Landis Tree)简介及Java实现

    平衡二叉树之AVL树(Adelson-Velsky and Landis Tree)简介及Java实现 标签:#二叉树##数据结构##自平衡二叉树# 时间:2018/10/27 09:30:01 作者 ...

  10. 使用Java实现平衡二叉树

    使用Java实现平衡二叉树 二叉树是一种较为复杂的数据结构,二叉树算法在数据查询时的时间复杂度为 O(log n)(n为保存元素个数). 但是普通的二叉树在数据添加和删除时很容易出现树结构不平衡问题 ...

最新文章

  1. 资源 | AI、神经网络、机器学习、深度学习以及大数据学习备忘单
  2. HEOI2016/TJOI2016 字符串问题
  3. Hadoop学习笔记—18.Sqoop框架学习
  4. 致力协同办公oa系统服务器设置,致力协同办公oa系统安装手册新.pdf
  5. WebSocket服务器端的日志重复打印问题
  6. discuz3.1用哪个版本php版本好,Discuz应用中心安装模板提示版本号不匹配适用于X3.3 X3.2 X3.1的解决方法...
  7. [收藏]SQL Server 索引结构及其使用
  8. Screaming Frog SEO Spider for Mac(网络爬虫软件)v16.0
  9. 论文笔记_S2D.05-2012-ECCV-从立体图像中提取与场景一致的三维对象和深度
  10. ACL2016最佳论文:通过交互学习语言游戏
  11. error LNK2019: 无法解析的外部符号 _WinMain@16
  12. 重庆c语言程序二级考试,优·历届重庆市计算机C语言二级考试试题及答案.doc
  13. 双网卡内外网同时使用
  14. rose怎么画业务流程图_如何用Rational rose创建类图
  15. 品牌设计与VI设计的不同之处
  16. 前端bugger 后端debug 介绍系统内部逻辑 压测新增订单接口 tps上不去 ,oom ,常见性能问题 ,性能分析思路
  17. MIUI12系统简单卡刷开发版获取Root超级权限的步骤
  18. 哪个牌子的投影仪更好?哪个品牌投影仪好
  19. 计算机学报和c类会议,ccf期刊目录_ccf_ccf a类
  20. openldap 集成 sssd

热门文章

  1. HDOJ1495 非常可乐(bfs)
  2. 机器学习常用的分类器比较
  3. 设置网页默认为360浏览器极速模式打开
  4. mini2440一线触摸驱动代码的位置
  5. 全国计算机平面设计资格证,政策透明—平面设计师证全国统一报名入口报考条件...
  6. 【R语言】Splatter,一个用于简单模拟单细胞RNA测序数据的R包
  7. 控制工程实践(5)——线性控制系统的稳态误差(之二)
  8. web前端 day11今日大纲
  9. python3.7批量爬取百度图片/搜狗图片
  10. 旧版VS安装 Visual Studio 2019/2017/2015官方安装教程