使用Java实现平衡二叉树

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

如何实现?

我们通过旋转完成
如:左旋转
怎么处理-进行左旋转

1.创建一个新的节点newnode(以4这个值创建),创建一个新的节点,值等于当前根节点的值

//把新节点的左子树设置了当前节点的左子树

2.newnode.left=left

//把新节点的右子树设置为当前节点的右子树的左子树

3.newnode.right=right.left

把当前节点的值换为右子节点的值

4.value=right.value

//把当前节点的右子树设置为右子树的右子树

5.right=right.right

把当前节点的左子树设置为新节点

6.left=newnode

平衡二叉树

具体代码:

public class BalancedBinaryTree<T> {private int size;private Node root;@SuppressWarnings("rawtypes")private Comparator comparator;public BalancedBinaryTree() {}@SuppressWarnings("rawtypes")public BalancedBinaryTree(Comparator comparator) {this.comparator = comparator;}public void add(T data) {Node node = new Node(data);Node p = findNode(node);if (p == null) {this.root = node;} else if (p.compare(node) > 0) {p.left = node;node.parent = p;} else if (p.compare(node) < 0) {p.right = node;node.parent = p;} else {p.data = data;return;}size++;handleImBalance4Add(node);}public boolean remove(T data) {if (root == null) {return false;}Node node = new Node(data);Node res = findNode(node);if (node.compare(res) != 0) {throw new NoSuchElementException();}Node checkPoint;if (res.left == null && res.right == null) {checkPoint = removeLeafNode(res);} else if (res.left == null || res.right == null) {checkPoint = removeNodeWithOneChild(res);} else {checkPoint = removeNodeWithTwoChild(res);}if (checkPoint != null) {handleImbalance4Remove(checkPoint);}size--;return true;}public int size() {return size;}private void handleImbalance4Remove(Node checkPoint) {Node tmp = checkPoint;boolean leftRemoved = false;if (tmp.left == null && tmp.right == null) {tmp.factor = 0;if (tmp.parent != null) {leftRemoved = tmp.parent.left == tmp;}tmp = tmp.parent;} else if (tmp.factor == 0) {tmp.factor = tmp.left == null ? 1 : -1;return;} else {leftRemoved = tmp.left == null;}int f;while (tmp != null) {f = tmp.factor;if (leftRemoved) {f = f + 1;} else {f = f - 1;}tmp.factor = f;if (f == -2 || f == 2) {tmp = handleImbalance(tmp);} else if (f == 1 || f == -1) {break;}leftRemoved = tmp.parent != null && tmp.parent.left == tmp;tmp = tmp.parent;}}private Node removeNodeWithTwoChild(Node node) {if (node.left == null || node.right == null) {throw new IllegalStateException("only use of two child node removing");}Node target = findDeepestAndClosestNodeOfCurrentNode(node);node.data = target.data;Node p = null;if (target.left == null && target.right == null) {p = removeLeafNode(target);} else if (target.left == null || target.right == null) {p = removeNodeWithOneChild(target);} else {//impossiblethrow new IllegalStateException("method of findDeepestAndClosestNodeOfCurrentNode work not right!");}return p;}private Node removeNodeWithOneChild(Node node) {Node parent = node.parent;Node child;if (node.left == null && node.right != null) {child = node.right;} else if (node.right == null && node.left != null) {child = node.left;} else {throw new IllegalStateException("only use of one child node removing");}child.parent = parent;if (parent == null) {root = child;} else if (parent.left == node) {parent.left = child;} else {parent.right = child;}return child;}private Node removeLeafNode(Node node) {if (node.left != null || node.right != null) {throw new IllegalStateException("only use of leaf child node removing");}Node parent = node.parent;if (parent != null) {if (parent.left == node) {parent.left = null;} else {parent.right = null;}} else {root = null;}return parent;}private Node findDeepestAndClosestNodeOfCurrentNode(Node node) {Node left = node.left;Node right = node.right;int i = 0, j = 0;Node targetLeft = left, targetRight = right;boolean bottom = false;for (; ; i++) {if (left.right != null) {left = left.right;} else {if (!bottom) {targetLeft = left;bottom = true;}if (left.left != null) {left = left.left;} else {break;}}}bottom = false;for (; ; j++) {if (right.left != null) {right = right.left;} else {if (!bottom) {targetRight = right;bottom = true;}if (right.right != null) {right = right.right;} else {break;}}}if (i >= j) {return targetLeft;} else {return targetRight;}}private void handleImBalance4Add(Node checkPoint) {Node tmp = checkPoint;Node p = tmp.parent;boolean tmpLeftFlag;int k;while (p != null) {tmpLeftFlag = p.left == tmp;if (tmpLeftFlag) {k = p.factor - 1;} else {k = p.factor + 1;}p.factor = k;if (k == 2 || k == -2) {handleImbalance(p);break;} else if (k == 0) {break;}tmp = p;p = p.parent;}}private Node handleImbalance(Node node) {Node res;int rotateType;int k = 0;if (node.factor == -2 && node.left.factor == -1) {res = RRR(node);rotateType = 1;} else if (node.factor == 2 && node.right.factor == 1) {res = LLR(node);rotateType = 2;} else if (node.factor == -2 && node.left.factor == 1) {k = node.left.right.factor;res = LRR(node);rotateType = 3;} else if (node.factor == 2 && node.right.factor == -1) {k = node.right.left.factor;res = RLR(node);rotateType = 4;} else {throw new RuntimeException("平衡因子计算错误");}handleFactorAfterReBalance(res, rotateType, k);return res;}private void handleFactorAfterReBalance(Node node, int rotateType, int originFactor) {node.factor = 0;if (rotateType == 1) {node.right.factor = 0;} else if (rotateType == 2) {node.left.factor = 0;} else if (rotateType == 3 || rotateType == 4) {if (originFactor == 1) {node.left.factor = -1;node.right.factor = 0;} else if (originFactor == -1) {node.left.factor = 0;node.right.factor = 1;} else {node.left.factor = 0;node.right.factor = 0;}}}private Node RRR(Node node) {Node parent = node.parent;Node child = node.left;child.parent = parent;node.parent = child;node.left = child.right;if (node.left != null) {node.left.parent = node;}child.right = node;if (parent == null) {root = child;} else if (parent.right == node) {parent.right = child;} else {parent.left = child;}return child;}private Node LLR(Node node) {Node parent = node.parent;Node child = node.right;child.parent = parent;node.parent = child;node.right = child.left;if (node.right != null) {node.right.parent = node;}child.left = node;if (parent == null) {root = child;} else if (parent.left == node) {parent.left = child;} else {parent.right = child;}return child;}private Node LRR(Node node) {LLR(node.left);return RRR(node);}private Node RLR(Node node) {RRR(node.right);return LLR(node);}private Node findNode(Node node) {Node p = null;Node tmp = root;while (tmp != null) {p = tmp;if (tmp.compare(node) > 0) {tmp = tmp.left;} else if (tmp.compare(node) < 0) {tmp = tmp.right;} else {break;}}return p;}private void traverse(Node node, Consumer<Node> consumer) {if (node == null) {return;}Deque<Node> nodeDeque = new ArrayDeque<>();node.height = 1;nodeDeque.add(node);while (nodeDeque.size() > 0) {Node first = nodeDeque.pollFirst();consumer.accept(first);Node right = first.right;if (right != null) {right.height = first.height + 1;nodeDeque.addFirst(right);}Node left = first.left;if (left != null) {left.height = first.height + 1;nodeDeque.addFirst(left);}}}@Overridepublic String toString() {StringBuilder res = new StringBuilder();traverse(root, n -> {for (int i = 0; i < n.height; i++) {res.append("----------");}res.append(':');res.append(n.data);res.append('(');res.append(n.factor);res.append(')');res.append('\n');});return res.toString();}private int getMaxHeight(Node node){int[] height = new int[1];traverse(node,n->{if(n.left == null && n.right == null && n.height > height[0]){height[0] = n.height;}});return height[0];}//查询public boolean contains(Comparable<T> data) {if (this.size == 0) {                                 // 没有数据return false ;                                       // 结束查询}return this.root.containsNode(data) ;                   // Node类查询}class Node {private Node parent;private Node left;private Node right;private int factor;private int height;private T data;public Node(T data) {Objects.requireNonNull(data);this.data = data;}public int compare(Node target) {if (comparator != null) {return comparator.compare(this.data, target.data);} else {return ((Comparable) this.data).compareTo(target.data);}}@Overridepublic String toString() {return data.toString();}public boolean containsNode(Comparable<T> data) {if (data.compareTo((T) this.data) == 0) {          // 数据匹配return true;                                     // 查找到了} else if (data.compareTo((T) this.data) < 0) {   // 左子节点查询if (this.left != null) {                      // 左子节点存在return this.left.containsNode(data);       // 递归调用} else {                                     // 没有左子节点return false;                              // 无法找到}} else {                                            // 右子节点查询if (this.right != null) {                     // 右子节点存在return this.right.containsNode(data);      // 递归调用} else {                                     // 没有右子节点return false;                              // 无法找到}}}}static BalancedBinaryTree<Integer> buildTestTree() {BalancedBinaryTree<Integer> binaryTree = new BalancedBinaryTree();binaryTree.add(8);binaryTree.add(3);binaryTree.add(13);binaryTree.add(1);binaryTree.add(5);binaryTree.add(10);binaryTree.add(16);binaryTree.add(2);binaryTree.add(4);binaryTree.add(7);binaryTree.add(9);binaryTree.add(12);binaryTree.add(15);binaryTree.add(18);binaryTree.add(6);binaryTree.add(11);binaryTree.add(14);binaryTree.add(17);binaryTree.add(19);binaryTree.add(20);return binaryTree;}

实例:

public class Binary {public static void main(String args[]) {BalancedBinaryTree<Integer> bbt = new BalancedBinaryTree<>();bbt.add(100);bbt.add(10);bbt.add(40);bbt.add(34);bbt.add(210);System.out.println(bbt);}
}

使用自定义数据结构

那我们实现自己类信息的排列呢?
很简单,只需将类加入Comparable接口就可以了

public class Emp implements Comparable<Emp>{private String ename ;private String job ;private Double salary ;private Integer age ;private Date hiredate ; private String dept ;public String getEname() {return ename;}public void setEname(String ename) {this.ename = ename;}public String getJob() {return job;}public void setJob(String job) {this.job = job;}public Double getSalary() {return salary;}public void setSalary(Double salary) {this.salary = salary;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Date getHiredate() {return hiredate;}public void setHiredate(Date hiredate) {this.hiredate = hiredate;}public String getDept() {return dept;}public void setDept(String dept) {this.dept = dept;}@Overridepublic int compareTo(Emp emp) {return this.age - emp.age;}
@Overridepublic String toString() {return "Emp [ename=" + ename + ", job=" + job + ", salary=" + salary + ", age=" + age + ", hiredate=" + hiredate+ ", dept=" + dept + "]";}
}

主类(我这里使用了自己做的一个属性自动配置工具):

public class Binary {public static void main(String args[]) {System.out.println("使用自定义数据");BalancedBinaryTree<Emp> b = new BalancedBinaryTree<>();String value = "ename:Smith|job:Clerk|salary:8960.00|age:30|hiredate:2003-10-15|"+ "dept.dname:财务部|dept.loc:MLDN|dept.company.name:SMD" ;String value2 = "ename:231213|job:Clerk|salary:8960.00|age:24|hiredate:2003-10-15|"+ "dept.dname:财务部|dept.loc:MLDN|dept.company.name:SMD" ;Emp emp = ClassInstanceFactory.create(Emp.class, value) ;  // 工具类自动设置Emp emp2 = ClassInstanceFactory.create(Emp.class, value2) ;  // 工具类自动设置String value3 = "ename:23|job:Clerk|salary:8960.00|age:43|hiredate:2003-10-15|"+ "dept.dname:财务部|dept.loc:MLDN|dept.company.name:Alibaba" ;Emp emp3 = ClassInstanceFactory.create(Emp.class, value3) ; // 工具类自动设置String value4 = "ename:23|job:Clerk|salary:8960.00|age:43|hiredate:2003-10-15|"+ "dept.dname:财务部|dept.loc:MLDN|dept.company.name:Alibaba" ;Emp emp4 = ClassInstanceFactory.create(Emp.class, value4) ; // 工具类自动设置b.add(emp);b.add(emp2);b.add(emp3);System.out.println(b);System.out.println(b.contains(emp4));//寻找存不存在和emp4一个属性的对象}
}

如果感觉有用就请给我点个免费的赞吧❥(^_-)

使用Java实现平衡二叉树相关推荐

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

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

  2. Java判断平衡二叉树

    输入一棵二叉树的根节点,判断该树是不是平衡二叉树.如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树. /*** Definition for a binary tree n ...

  3. 带你彻底弄明白!java实现平衡二叉树

    一面: 先是问了问项目,然后就开始问一些问题 1.每个请求耗时100ms,机器的配置是4核8G,问要达到10000TPS需要多少台机器? 没答上来,问了问是IO密集型还是CPU密集型,然后面试官说我想 ...

  4. java实现平衡二叉树

    本文参考海纳的两篇文章,需要补平衡二叉树知识的请看这里. 参照的文章是这篇文章. 可以直接去看这两篇文章,再回头看我这篇文章,所以我就去繁就简. 代码 package com.yubotao;/*** ...

  5. 用Java实现平衡二叉树

    ​平衡二叉树的定义 在谈平衡二叉树之前,首先了解一下二叉排序树.空树或者具有以下特性的二叉树就是二叉排序树: 若左子树非空,则左子树上所有结点关键字的值均小于根节点的关键字的值. 若右子树非空,则右子 ...

  6. Java数据结构——平衡二叉树(AVL树)

    AVL树的引入 搜索二叉树有着极高的搜索效率,但是搜索二叉树会出现以下极端情况: 这样的二叉树搜索效率甚至比链表还低.在搜索二叉树基础上出现的平衡二叉树(AVL树)就解决了这样的问题.当平衡二叉树(A ...

  7. Java 求解平衡二叉树

    文章目录 一.题目 二.题目分析 三.迭代法 四.总结 一.题目 给定一个二叉树,判断它是否是高度平衡的二叉树. 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值 ...

  8. Java 判断平衡二叉树

    /*** @author 陈明勇*/ public class AvlTree {private Boolean isAvlTree(TreeNode treeNode) {if (treeNode ...

  9. java循环遍历类属性_java循环遍历类属性 get 和set值方法

    //遍历sqspb类 成员为String类型 属性为空的全部替换为"/" Field[] fields = sqspb.getClass().getDeclaredFields() ...

最新文章

  1. idea ssm框架 mysql_idea搭建简单ssm框架的最详细教程(新)
  2. leangoo自由配置任务卡片(需求、迭代、bug)自定义字段
  3. 面试题:在日常工作中怎么做MySQL优化的?
  4. 数据状态更新时的差异 diff 及 patch 机制
  5. Spring-Logback-动态修改日志级别
  6. AIDL实现不同应用间的通信
  7. php与ununtu通信,Ubuntu 20.04 LTS 已引入 PHP 7.4
  8. 常见Git分支使用方式
  9. VC 2014 QQ连连看外挂辅助(讲解,附带下载) CE QQ连连看基址
  10. 推荐系统遇上深度学习(十二)--推荐系统中的EE问题及基本Bandit算法
  11. LaTeX - 如何在图片说明(caption)中使用脚注(footnote)
  12. 威联通 nas mysql_威联通(NAS)应用篇:自建OwnCloud网盘(百度网盘,拜拜~~~)
  13. 常见的qq在线客服代码
  14. C语言 输出Sn = a + aa + aaa + aaaa + ······
  15. php weixin provider,14、ABPZero系列教程之拼多多卖家工具 新建微信公众号模块
  16. 前端岗位一般的任职要求
  17. 树莓派 摄像头mjpg-streamer视频推流+开机自启动
  18. 三星为企业服务器开发高性能PCIe 5.0固态硬盘;阳狮集团升任张珲杰为明思力中国董事总经理 | 全球TMT...
  19. time_t、SYSTEMTIME、CTime、COleDateTime互转
  20. (邻接表/邻接矩阵)图的实现

热门文章

  1. UI设计需要学会哪些软件?
  2. 学UI设计,用对这5款设计软件是关键
  3. scanf(%*s)
  4. web前端期末大作业——开心旅游网站设计与实现(HTML+CSS+JavaScript)
  5. jupyther_python基础系列 09 第九章 有益的探索
  6. run vue task的项目报错:Error while running task C:\IT\xxxxxx:serve with message‘spawn vue-cli-service
  7. 哥尼斯堡的“七桥问题” (25分)
  8. 内卷、躺平与中年危机的相关思考
  9. 【web前端开发 | CSS】页面布局之盒子模型
  10. 【转载】国内主要的量化交易平台及链接