1. package com.test.tree;
  2.  
  3. /**
  4. * 带有平衡条件的二叉查找树
  5. * */
  6. public class AVLBinarySearchTree<T extends Comparable<? super T>> {
  7.  
  8. /*内部类,定义二叉树中的节点结构*/
  9. private static class TreeNode<T>{
  10. private T data; //节点的值
  11. private TreeNode<T> lt; //节点左子树
  12. private TreeNode<T> rt; //节点右子树
  13. private int height; //用来记录节点的高度,进行单旋转或双旋转
  14.  
  15. public TreeNode(T data) {
  16. this(data, null, null);
  17. }
  18. public TreeNode(T data, TreeNode<T> lt, TreeNode<T> rt) {
  19. this.data = data;
  20. this.lt = lt;
  21. this.rt = rt;
  22. this.height = 0;
  23. }
  24. public T getData() {
  25. return data;
  26. }
  27. public void setData(T data) {
  28. this.data = data;
  29. }
  30. public TreeNode<T> getLt() {
  31. return lt;
  32. }
  33. public void setLt(TreeNode<T> lt) {
  34. this.lt = lt;
  35. }
  36. public TreeNode<T> getRt() {
  37. return rt;
  38. }
  39. public void setRt(TreeNode<T> rt) {
  40. this.rt = rt;
  41. }
  42. public int getHeight() {
  43. return height;
  44. }
  45. public void setHeight(int height) {
  46. this.height = height;
  47. }
  48. }
  49.  
  50. /**
  51. * 计算节点的高度
  52. * @param t 输入子树
  53. * @return 返回树的高度
  54. */
  55. public int height(TreeNode<T> t){
  56. return t==null ? -1 : t.height;
  57. }
  58.  
  59. /**
  60. * 给树中添加节点
  61. * @param data 要插入的节点值
  62. * @param t 要插入的子树
  63. * @return 插入后形成的新的树
  64. */
  65. public TreeNode<T> insert(T data, TreeNode<T> t){
  66. if(t == null){
  67. //树为空
  68. return new TreeNode<T>(data, null ,null);
  69. }
  70. int compareReslt = compare(data, t.data);
  71. if(compareReslt < 0){
  72. //插入的数小于节点数,放入左子树中
  73. t.lt = insert(data, t.lt) ; //递归插入左子树
  74.  
  75. //插入后检查当前节点的左右子树是否平衡
  76. if(height(t.lt)-height(t.rt) == 2){
  77. if(compare(data, t.lt.data) < 0){
  78. t = rotateWithLeftChild(t); //单旋转
  79. }else if(compare(data, t.lt.data) > 0){
  80. t = doubleWithLeftChild(t); //双旋转
  81. }
  82. }
  83. }else if(compareReslt > 0){
  84. //插入的数大于节点数,放入右子树中
  85. t.rt = insert(data, t.rt) ; //递归插入左子树
  86.  
  87. //插入后检查当前节点的左右子树是否平衡
  88. if(height(t.rt)-height(t.lt) == 2){
  89. if(compare(data, t.rt.data) > 0){
  90. t = rotateWithRightChild(t); //单旋转
  91. }else if(compare(data, t.rt.data) > 0){
  92. t = doubleWithRightChild(t); //双旋转
  93. }
  94. }
  95. }
  96. t.height = Math.max(height(t.lt), height(t.rt)) + 1;
  97. return t;
  98. }
  99. private TreeNode<T> rotateWithRightChild(TreeNode<T> k2) {
  100. // TODO Auto-generated method stub
  101. TreeNode<T> k1 = k2.rt;
  102. k2.rt = k1.lt; //左子树的右节点介于左子树根节点和根节点之间,赋值给根节点的左子树
  103. k1.lt = k2; //将根节点赋值给左节点的右节点
  104. k2.height = Math.max(height(k2.lt), height(k2.rt)) + 1;
  105. k1.height = Math.max(height(k1.rt), k2.height) + 1;
  106. return k1;
  107. }
  108.  
  109. private TreeNode<T> doubleWithRightChild(TreeNode<T> k3) {
  110. // TODO Auto-generated method stub
  111. k3.rt = rotateWithLeftChild(k3.rt);
  112. return rotateWithRightChild(k3);
  113. }
  114.  
  115. /**
  116. * 单旋转
  117. * @param t
  118. * @return
  119. */
  120. private TreeNode<T> rotateWithLeftChild(TreeNode<T> k2) {
  121. // TODO Auto-generated method stub
  122. TreeNode<T> k1 = k2.lt; //左子树的根节点赋给K1
  123. k2.lt = k1.rt; //左子树的右节点介于左子树根节点和根节点之间,赋值给根节点的左子树
  124. k1.rt = k2; //将根节点赋值给左节点的右节点
  125. k2.height = Math.max(height(k2.lt), height(k2.rt)) + 1;
  126. k1.height = Math.max(height(k1.lt), k2.height) + 1;
  127. return k1;
  128. }
  129. /**
  130. * 双旋转
  131. * @param t
  132. * @return
  133. */
  134. private TreeNode<T> doubleWithLeftChild(TreeNode<T> k3) {
  135. // TODO Auto-generated method stub
  136. k3.lt = rotateWithRightChild(k3.lt);
  137. return rotateWithLeftChild(k3);
  138. }
  139.  
  140. /**
  141. * 比较两个值是否相等
  142. * @param data1
  143. * @param data2
  144. * @return
  145. */
  146. public int compare(T data1, T data2){
  147. return data1.compareTo(data2);
  148. }
  149.  
  150. /*中序遍历*/
  151. public void printTree(TreeNode<T> t){
  152. if(t != null){
  153. printTree(t.lt);
  154. System.out.print(t.data+"、");
  155. printTree(t.rt);
  156. }
  157. }
  158.  
  159. public static void main(String[] args) {
  160. AVLBinarySearchTree<Integer> aVLBinarySearchTree = new AVLBinarySearchTree<Integer>();
  161. TreeNode<Integer> node = new TreeNode<Integer>(8);
  162. node = aVLBinarySearchTree.insert(6, node);
  163. node = aVLBinarySearchTree.insert(16, node);
  164. node = aVLBinarySearchTree.insert(13, node);
  165. node = aVLBinarySearchTree.insert(19, node);
  166. node = aVLBinarySearchTree.insert(7, node);
  167. node = aVLBinarySearchTree.insert(21, node);
  168. node = aVLBinarySearchTree.insert(23, node);
  169. aVLBinarySearchTree.printTree(node.lt);
  170. aVLBinarySearchTree.printTree(node.rt);
  171. }
  172. }

平衡二叉树--java的更多相关文章

  1. 平衡二叉树 JAVA实现 亲测可用

    平衡二叉树的JAVA实现 亲测可用 包括LL LR RL RR四种情况的旋转算法 以及添加删除树结点之后对平衡二叉树的维护算法 都已经实现并测试过 没有问题. 代码地址可以直接上我的GIT clone ...

  2. 数据结构-平衡二叉树Java实现

    1,Node.java package com.cnblogs.mufasa.BalanceBinaryTree; public class Node { Node parent; Node left ...

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

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

  4. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  5. Java实现平衡二叉树(AVLTree)的构建

    近期在学习数据结构上关于平衡二叉树的知识,看了严老师的思路,感觉用java写出递归的构建方式有点困难,由于当中的递归须要把引用传进去,所以感觉是要实现起来比較麻烦,所以就首先想到使用非递归的方式来实现 ...

  6. 平衡二叉树(AVL)java实现

    数的节点 package com.ydp.tree.AVLTree; public class Node{ private int data = 0; private Node lchild = nu ...

  7. 平衡二叉树的java实现

    转载请注明出处! 一.概念 平衡二叉树是一种特殊的二叉搜索树,关于二叉搜索树,请查看上一篇博客二叉搜索树的java实现,那它有什么特别的地方呢,了解二叉搜索树的基本都清楚,在按顺序向插入二叉搜索树中插 ...

  8. 【Java】 剑指offer(55-2) 平衡二叉树

      本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 输入一棵二叉树的根结点,判断该树是不是平衡二叉树.如果某二叉树 ...

  9. 【Java】 大话数据结构(12) 查找算法(3) (平衡二叉树(AVL树))

    本文根据<大话数据结构>一书及网络资料,实现了Java版的平衡二叉树(AVL树). 平衡二叉树介绍 在上篇博客中所实现的二叉排序树(二叉搜索树),其查找性能取决于二叉排序树的形状,当二叉排 ...

随机推荐

  1. 如何枚举 Windows 顶级桌面窗口?

    bool is_top_level_window(HWND hwnd) { if (!IsWindow(hwnd)) return false; DWORD dw_style = GetWindowL ...

  2. jQuery中删除节点方法remove()、detach()、empty()分析

    jQuery中提供了三种删除节点的方法:remove().detach().empty(),本文详细分析这三种方法. 最容易区分的是empty(),该方法严格上属于“清空节点”,即删除其子节点,自身并 ...

  3. 数据库质疑修复(SUSPECT)总结,DBCC报错

    当SQL SERVER数据库状态为质疑(SUSPECT)状态时,我们可以用以下方法来处理: DBCC报错 1. 修改数据库为紧急模式:ALTER DATABASE DBName SET EMERGEN ...

  4. Hexo+yilia添加helper-live2d插件宠物动画,很好玩的哦~~

    个人主页:https://www.yuehan.online 现在博客:www.wangyurui.top 安装模块: 博客根目录选择cmd命令窗口或者git bash 输入以下代码,安装插件 操作: ...

  5. Oracle学习笔记—数据字典和常用命令(转载)

    转载自: oracle常用数据字典和SQL语句总结 Oracle常用命令大全(很有用,做笔记) 一.Oracle数据字典 数据字典是Oracle存放有关数据库信息的地方,其用途是用来描述数据的.比如一 ...

  6. 判断数A和数B中有多少个位不相同

    1. A & B,得到的结果C中的1的位表明了A和B中相同的位都是1的位:2. A | B, 得到的结果D中的1的位表明了A和B在该位至少有一个为1的位,包含了A 与 B 都是1的位数,经过前 ...

  7. ansible的主机变量

    ansible的主机变量(常用):ansible_ssh_host     #用于指定被管理的主机的真实IPansible_ssh_port     #用于指定连接到被管理主机的ssh端口号,默认是2 ...

  8. FSR薄膜压力传感器使用教程

    FSR薄膜压力传感器教程 本店常用的外形有2种: 圆形: 长条形: 如果用单片机控制建议买带转换的,可以直接接单片机AD口或者数字IO去读取数值: 电压输出的AO接口是模拟量输出,可以接单片机的模拟口 ...

  9. 爬虫二 requests模块的使用

    一.requests模块的介绍 #介绍:使用requests可以模拟浏览器的请求,比起之前用到的urllib,requests模块的api更加便捷(本质就是封装了urllib3) #注意:reques ...

  10. 剑指offer 面试27题

    面试27题: 题目:二叉树的镜像 题:操作给定的二叉树,将其变换为源二叉树的镜像. 输入描述: 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / ...