平衡二叉查找树(JAVA)
2017-02-10 16:51
417 查看
之前我分享过二叉查找树(也叫二叉排序树)的BST博客
平衡二叉排序树定义(1)首先整体为二叉查找树。(2)左子树与右子树的深度之差的绝对值小于或等于1。 (3),左右子树也是平衡二叉查找树。
所以平衡二叉排序树就是为了维护“树”的基本形态。
如果一棵树所有节点的平很因子都是(0,1,-1),那么此树就为平衡二叉排序树。
B节点:就是该祖先节点一条线中A节点的下一个。
C节点:这个节点有可能用上也有可能没用,当非平衡树的状态类型为LR或者RL型时,C节点就是B节点的子节点(左右根据大小来放置)。其它类型C节点无用处。
(1)LL型
(2)RR型
(3)LR型
(4)RL型 与(3)同理
示例代码运行结果:
二叉排序树 与 平衡二叉排序树
俩者官方定义
二叉排序树定义就是(1)任何节点的左节点值都比当前根节点值小。(2)所有右节点值都比当前根节点值大。 (3)且所有子树也都是二叉排序树。平衡二叉排序树定义(1)首先整体为二叉查找树。(2)左子树与右子树的深度之差的绝对值小于或等于1。 (3),左右子树也是平衡二叉查找树。
我们有了二叉排序树为什么我们还需要平衡二叉排序树?
大家都知道树的结构其实也算是链表的一种变形,所以在最坏情况下树有可能变成线性的链表,那么此时遍历的效率(平均查找长度)很比较差(长),也失去了树的结构定义的初衷。所以平衡二叉排序树就是为了维护“树”的基本形态。
平衡二叉排序树
平衡因子
平衡因子存储在节点当中,其含义就是当前节点的左子树深度与右子树深度之差。如果一棵树所有节点的平很因子都是(0,1,-1),那么此树就为平衡二叉排序树。
其中的特殊点
A节点:为插入点顶层“祖先节点”中最大可能的失衡点(提醒一下最可能的往往是平衡因子不为0的节点,之后程序示例中会体现出来)。如果没有找到,说明插入这个节点不可能破坏平衡B节点:就是该祖先节点一条线中A节点的下一个。
C节点:这个节点有可能用上也有可能没用,当非平衡树的状态类型为LR或者RL型时,C节点就是B节点的子节点(左右根据大小来放置)。其它类型C节点无用处。
四个非平衡状态时的转换类型
图片来自博客一个技术人员的草稿纸,侵删(1)LL型
(2)RR型
(3)LR型
(4)RL型 与(3)同理
平衡二叉排序树代码实现
class TreeNode { int value; int bf; //平衡因子 TreeNode left_node; TreeNode right_node; public TreeNode(int value, int bf) { this.bf = bf; this.value = value; this.left_node = null; this.right_node = null; } } public class BalanceBinaryTree { private final int LL = 1; private final int RR = 2; private final int LR = 3; private final int RL = 4; private TreeNode RootNode; public void insert(int value) { int choice = 0; TreeNode A = RootNode; TreeNode B = null; TreeNode C = null; TreeNode Father_A = null; TreeNode HelpNode = null; TreeNode CurrentNode = RootNode; //创建要插入的节点 TreeNode node = new TreeNode(value, 0); //如果一开始根节点为空,直接将当前值设置为根节点 if(RootNode == null) { RootNode = node; return; } //找到要插入的节点,并且找到最可能失去平衡点的节点A,Father_A为A的父节点 while (CurrentNode != null) { if(CurrentNode.bf !=0 ) { A = CurrentNode; Father_A = HelpNode; } HelpNode = CurrentNode; if(CurrentNode.value < value) { CurrentNode = CurrentNode.right_node; } else { CurrentNode = CurrentNode.left_node; } } //插入目标节点 if(HelpNode.value < value) { HelpNode.right_node = node; } else { HelpNode.left_node = node; } //确定B节点,并修改A的平衡因子bf if(value < A.value) { B = A.left_node; A.bf = A.bf + 1; } else { B = A.right_node; A.bf = A.bf - 1; } //修改其它节点的平衡因子bf CurrentNode = B; while (CurrentNode != node) { if(value < CurrentNode.value) { CurrentNode.bf = 1; CurrentNode = CurrentNode.left_node; } else { CurrentNode.bf = -1; CurrentNode = CurrentNode.right_node; } } if(A.bf == 2 && B.bf == 1) { choice = LL; } else if(A.bf == -2 && B.bf == -1) { choice = RR; } else if(A.bf == 2 && B.bf == -1) { choice = LR; } else if(A.bf == -2 && B.bf == 1) { choice = RL; } else { choice = 0; } switch (choice) { case LL: B = A.left_node; A.left_node = B.right_node; B.right_node = A; A.bf = B.bf = 0; if(Father_A == null) { RootNode = B; } else if (A == Father_A.left_node) { Father_A.left_node = B; } else { Father_A.left_node = B; } break; case LR: B = A.left_node; C = B.right_node; B.right_node = C.left_node; A.left_node = C.right_node; C.left_node = B; C.right_node = A; if(node.value < C.value) { A.bf = -1; B.bf = 0; C.bf = 0; } else if(node.value > C.value) { A.bf = 0; B.bf = 1; C.bf = 0; } else { A.bf = 0; B.bf = 0; } if(Father_A == null) RootNode = C; else if(A == Father_A.left_node) { Father_A.left_node = C; } else { Father_A.right_node = C; } break; case RL: B = A.right_node; C = B.left_node; B.left_node = C.right_node; A.right_node = C.left_node; C.left_node = A; C.right_node = B; if(node.value < C.value) { A.bf = 0; B.bf = -1; C.bf = 0; } else if(node.value > C.value) { A.bf = 1; B.bf = 0; C.bf = 0; } else { A.bf = 0; B.bf = 0; } if(Father_A == null) RootNode = C; else if(A == Father_A.left_node) { Father_A.left_node = C; } else { Father_A.ri bd90 ght_node = C; } break; case RR: B = A.right_node; A.right_node = B.left_node; B.left_node = A; A.bf = B.bf = 0; if(Father_A == null) RootNode = B; else if(A==Father_A.left_node) { Father_A.left_node = B; } else { Father_A.right_node = B; } break; default: System.out.println("插入一个节点时没有破坏原有的平衡状态"); break; } return ; } private void FirstOrder(TreeNode node) { if(node != null) { System.out.print(node.value + " "); FirstOrder(node.left_node); FirstOrder(node.right_node); } } private void InOrder(TreeNode node) { if(node != null) { FirstOrder(node.left_node); System.out.print(node.value + " "); FirstOrder(node.right_node); } } private void PostOrder(TreeNode node) { if(node != null) { PostOrder(node.right_node); System.out.print(node.value + " "); PostOrder(node.left_node); } } //搜索节点 private TreeNode Search(TreeNode rootNode, int value) { while (rootNode != null) { if(rootNode.value == value) { return rootNode; } else if(rootNode.value > value) { rootNode = rootNode.left_node; } else { rootNode = rootNode.right_node; } } return null; } public static void main(String[] args) { BalanceBinaryTree balanceBinaryTree = new BalanceBinaryTree(); balanceBinaryTree.insert(20); balanceBinaryTree.insert(30); balanceBinaryTree.insert(25); balanceBinaryTree.insert(40); balanceBinaryTree.insert(60); System.out.print("先序遍历:"); balanceBinaryTree.FirstOrder(balanceBinaryTree.RootNode); System.out.println(); System.out.print("中序遍历:"); balanceBinaryTree.InOrder(balanceBinaryTree.RootNode); System.out.println(); System.out.print("后序遍历:"); balanceBinaryTree.PostOrder(balanceBinaryTree.RootNode); System.out.println(); } }
示例代码运行结果:
相关文章推荐
- Java 简述对象克隆(复制)
- java中exception的printStackTrace()输出内容转成字符串
- zip4j -- Java处理zip压缩文件的完整解决方案
- JAVA--基本数据类型
- 生成动态报表的Java项目打成.jar包文件运行时出错
- 01--Java集合知识
- 一套java swing框架
- Java VM Options
- Java多线程Thread,Runnable, Callable<>和线程池(一)
- 第五届校内选拔javaB组-第七道题敢死队
- java概述
- Eclipse 通过JPA自动生成注解实体
- 优秀的博文链接
- Java基础-12总结Scanner,String
- Java基础-12总结Scanner,String
- java getGeneratedKeys(获取自动递增主键)
- Java中JSON格式的简单应用例子
- Eclipse统计项目代码行数
- 加法变乘法
- ssm框架整合配置