当前位置:   article > 正文

数据结构(6)树形结构——平衡二叉树(JAVA代码实现)_java实现平衡二叉树

java实现平衡二叉树

目录

6.1.概述

6.2.AVL树

6.2.1.概述

6.2.2.旋转

1.RR旋转

 2.LL旋转

3.LR旋转

4.RL旋转

 6.2.3.代码实现


6.1.概述

二叉搜索树存在一个问题,就是树的姿态和数据的插入顺序是有关系的,有时候树会变成某一边的子树高度过高,甚至直接退化成斜二叉树,使得查找从二分查找跌落为顺序查找:

保证任意结点左右子树的高度一致,便可以保证树的查询效率为最优,但是此种情况过于理想,难以达到,因此允许左右子树的高度间存在差异,于是出现了平衡二叉树,即任意结点左右子树高度差不超过1:

每次操作后出现有结点的左右子树高度差超过1的情况时,树会自己进行调整姿态,重新达到平衡。

平衡二叉树只是一种思想,有很多种实现,常见的实现有红黑树、AVL、Treap、伸展树等。

6.2.AVL树

6.2.1.概述

AVL是出现的第一种平衡二叉树,每当插入元素,造成AVL树的不平衡后,它会通过旋转的方式调整最小不平衡树,从而将树调整平衡。插入后造成不平衡的元素叫“破坏者”,最小不平衡树的根节点叫“被破坏者”。

最小不平衡树,即从高度差超过1的两条分支开始向上找,找到它们的第一个共同父结点,以这个父节点为根结点的子树就是最小不平衡树。

AVL的旋转有四种:

  • RR旋转
  • LL旋转
  • LR旋转
  • RL旋转

6.2.2.旋转

1.RR旋转

“破坏者”在右子树的右子树,执行RR旋转,将“被破坏者”的右孩子提为根节点,该右孩子的左子树移植为“被破坏者”的右子树。

 2.LL旋转

“破坏者”在左子树的左子树,就执行LL旋转,将“被破坏者”压为“破坏者”父节点的右孩子,“破坏者”父节点往上走一层。

3.LR旋转

破坏者在左子树的右子树,就执行LR旋转,步骤和LL旋转相同,将“被破坏者”压为“破坏者”父节点的右孩子,“破坏者”父节点往上走一层。

4.RL旋转

破坏者在右子树的左子树执行RL旋转,调整被破坏者,被破坏者的R,以及被破坏者R的L(这里可能有点晕,其实仔细观察会发现其实就是契合右子树的左子树这个位置关系。),被破坏者的R提上,被破坏者的R的L不变。

 6.2.3.代码实现

  1. public class AvlTree<T extends Comparable<? super T>> {
  2. private AvlNode<T> root;
  3. public void insert(T x) {
  4. root = insert(x, root);
  5. }
  6. public void remove(T x) {
  7. root = remove(x, root);
  8. }
  9. public T findMin() {
  10. return findMin(root).element;
  11. }
  12. public void makeEmpty() {
  13. root = null;
  14. }
  15. public boolean isEmpty() {
  16. return root == null;
  17. }
  18. /**
  19. * 添加节点
  20. *
  21. * @param x 插入节点
  22. * @param t 父节点
  23. */
  24. private AvlNode<T> insert(T x, AvlNode<T> t) {
  25. //如果根节点为空,则当前x节点为根及诶单
  26. if (null == t) {
  27. return new AvlNode(x);
  28. }
  29. int compareResult = x.compareTo(t.element);
  30. //小于当前根节点 将x插入根节点的左边
  31. if (compareResult < 0) {
  32. t.left = insert(x, t.left);
  33. } else if (compareResult > 0) {
  34. //大于当前根节点 将x插入根节点的右边
  35. t.right = insert(x, t.right);
  36. } else {
  37. }
  38. return balance(t);
  39. }
  40. private static final int ALLOWED_IMBALANCE = 1;
  41. private AvlNode<T> balance(AvlNode<T> t) {
  42. if (t == null) {
  43. return t;
  44. }
  45. if (height(t.left) - height(t.right) > ALLOWED_IMBALANCE) {
  46. if (height(t.left.left) >= height(t.left.right)) {
  47. t = rotateWithLeftChild(t);
  48. } else {
  49. t = doubleWithLeftChild(t);
  50. }
  51. } else if (height(t.right) - height(t.left) > ALLOWED_IMBALANCE) {
  52. if (height(t.right.right) >= height(t.right.left)) {
  53. t = rotateWithRightChild(t);
  54. } else {
  55. t = doubleWithRightChild(t);
  56. }
  57. }
  58. t.height = Math.max(height(t.left), height(t.right)) + 1;
  59. return t;
  60. }
  61. private AvlNode<T> doubleWithRightChild(AvlNode<T> k3) {
  62. k3.right = rotateWithLeftChild(k3.right);
  63. return rotateWithRightChild(k3);
  64. }
  65. private AvlNode<T> rotateWithRightChild(AvlNode<T> k2) {
  66. AvlNode k1 = k2.right;
  67. k2.right = k1.left;
  68. k1.left = k2;
  69. k2.height = Math.max(height(k2.right), height(k2.left)) + 1;
  70. k1.height = Math.max(height(k1.right), k2.height) + 1;
  71. return k1;
  72. }
  73. private AvlNode<T> doubleWithLeftChild(AvlNode<T> k3) {
  74. k3.left = rotateWithRightChild(k3.left);
  75. return rotateWithLeftChild(k3);
  76. }
  77. private AvlNode<T> rotateWithLeftChild(AvlNode<T> k2) {
  78. AvlNode k1 = k2.left;
  79. k2.left = k1.right;
  80. k1.right = k2;
  81. k2.height = Math.max(height(k2.left), height(k2.right)) + 1;
  82. k1.height = Math.max(height(k1.left), k2.height) + 1;
  83. return k1;
  84. }
  85. private int height(AvlNode<T> t) {
  86. return t == null ? -1 : t.height;
  87. }
  88. /**
  89. * 删除节点
  90. *
  91. * @param x 节点
  92. * @param t 父节点
  93. */
  94. private AvlNode<T> remove(T x, AvlNode<T> t) {
  95. if (null == t) {
  96. return t;
  97. }
  98. int compareResult = x.compareTo(t.element);
  99. //小于当前根节点
  100. if (compareResult < 0) {
  101. t.left = remove(x, t.left);
  102. } else if (compareResult > 0) {
  103. //大于当前根节点
  104. t.right = remove(x, t.right);
  105. } else if (t.left != null && t.right != null) {
  106. //找到右边最小的节点
  107. t.element = findMin(t.right).element;
  108. //当前节点的右边等于原节点右边删除已经被选为的替代节点
  109. t.right = remove(t.element, t.right);
  110. } else {
  111. t = (t.left != null) ? t.left : t.right;
  112. }
  113. return balance(t);
  114. }
  115. /**
  116. * 找最小节点
  117. *
  118. * @param root 根节点
  119. */
  120. private AvlNode<T> findMin(AvlNode<T> root) {
  121. if (root == null) {
  122. return null;
  123. } else if (root.left == null) {
  124. return root;
  125. }
  126. return findMin(root.left);
  127. }
  128. /**
  129. * 找最大节点
  130. *
  131. * @param root 根节点
  132. */
  133. private AvlNode<T> findMax(AvlNode<T> root) {
  134. if (root == null) {
  135. return null;
  136. } else if (root.right == null) {
  137. return root;
  138. } else {
  139. return findMax(root.right);
  140. }
  141. }
  142. public void printTree() {
  143. if (isEmpty()) {
  144. System.out.println("节点为空");
  145. } else {
  146. printTree(root);
  147. }
  148. }
  149. public void printTree(AvlNode<T> root) {
  150. if (root != null) {
  151. System.out.print(root.element);
  152. if (null != root.left) {
  153. System.out.print("左边节点" + root.left.element);
  154. }
  155. if (null != root.right) {
  156. System.out.print("右边节点" + root.right.element);
  157. }
  158. System.out.println();
  159. printTree(root.left);
  160. printTree(root.right);
  161. }
  162. }
  163. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/528253
推荐阅读
相关标签
  

闽ICP备14008679号