1 import DataStructure.Tree_new.BST; 2 3 import java.util.Comparator; 4 5 public class AVLTree<E> extends BST<E> { 6 public AVLTree(){ 7 this(null); 8 } 9 public AVLTree(Comparator<E> comparator){ 10 super(comparator); 11 } 12 13 @Override 14 //这里的node是新添加的节点,1.往上找parent,找到失衡的最低高度的节点,让他平衡,然后其他节点也平衡了 15 protected void afterAdd(Node<E> node) { 16 while ((node=node.parent)!=null){ 17 //如果平衡,更新高度,不递归因为性能太差了 18 if(isBanlanced(node)) 19 { 20 updateHeight(node); 21 }else{ 22 //恢复平衡,能来到这里的节点是高度最低的不平衡的节点 23 rebalance(node); 24 break; 25 } 26 } 27 }
28 /** 29 * 统一旋转 30 */ 31 private void rotate( 32 Node<E> r, // 子树的根节点 33 Node<E> b, Node<E> c, 34 Node<E> d, 35 Node<E> e, Node<E> f) { 36 // 让d成为这棵子树的根节点 37 d.parent = r.parent; 38 if (r.isLeftChild()) { 39 r.parent.left = d; 40 } else if (r.isRightChild()) { 41 r.parent.right = d; 42 } else { 43 root = d; 44 } 45 46 //b-c 47 b.right = c; 48 if (c != null) { 49 c.parent = b; 50 } 51 updateHeight(b); 52 53 // e-f 54 f.left = e; 55 if (e != null) { 56 e.parent = f; 57 } 58 updateHeight(f); 59 60 // b-d-f 61 d.left = b; 62 d.right = f; 63 b.parent = d; 64 f.parent = d; 65 updateHeight(d); 66 } 67 68 private void rebalance(Node<E> grand) { 69 Node<E> parent = ((AVLnode<E>) grand).tallerChild(); 70 Node<E> node = ((AVLnode<E>) parent).tallerChild(); 71 if (parent.isLeftChild()) {//L 72 if (node.isLeftChild()) {//LL 73 rotate(grand, node, node.right, parent, parent.right, grand); 74 } else {//LR 75 rotate(grand, parent, node.left, node, node.right, grand); 76 } 77 } else {//R 78 if (node.isLeftChild()) {//RL 79 rotate(grand, grand, node.left, node, node.right, parent); 80 } else {//RR 81 rotate(grand, grand, parent.left, parent, node.left, node); 82 } 83 } 84 } 85 86
87 /** 88 * 恢复平衡,核心 89 * 这个node是高度最低的不平衡的节点 90 */ 91 private void rebance2(Node<E> grand){ 92 Node<E> parent =((AVLnode<E>)grand).tallerChild(); 93 Node<E> node =((AVLnode<E>)parent).tallerChild(); 94 if(parent.isLeftChild()){ 95 if(node.isLeftChild()){//LL的情况 96 rotateright(grand); 97 } 98 else {//LR的情况 99 rotateleft(parent); 100 rotateright(grand); 101 } 102 } 103 else {//一开始就是R 104 if(node.isLeftChild() ){//RL的情况 105 rotateright(parent); 106 rotateleft(grand); 107 } 108 else {//RR的情况 109 rotateleft(grand); 110 } 111 } 112 } 113 private void rotateleft(Node<E> grand){ 114 Node<E> parent =grand.right;//先找到P点,就是g点的右子树 115 Node<E> child =parent.left;//T1 116 grand.right=child; 117 parent.left=grand; 118 afterRotate(grand,parent,child); 119 } 120 private void rotateright(Node<E> grand){ 121 Node<E> parent =grand.left;//先找到P点,就是g点的左子树 122 Node<E> child =parent.right;//T2 123 grand.left=child; 124 parent.right=grand; 125 afterRotate(grand,parent,child); 126 127 } 128 //把旋转后的相同的操作整合到一个函数,为了美观 129 private void afterRotate(Node<E> grand,Node<E>parent,Node<E> child){ 130 //更新T1,p,g的父节点,如果g是左子树,那么左旋转后,p应该也是g的父节点的左子树 131 if(grand.isLeftChild()){ 132 grand.parent.left=parent; 133 } 134 else if(grand.isRightChild()){ 135 grand.parent.right=parent; 136 } 137 else { 138 //grand是跟节点 139 root=parent; 140 } 141 //更新childe(t1)的parent 142 if(child!=null){ 143 child.parent=grand; 144 } 145 //更新grand的parent 146 grand.parent=parent; 147 //更新高度 148 updateHeight(grand); 149 updateHeight(parent); 150 } 151 152 @Override 153 protected void afterRemove(Node<E> node) { 154 while ((node = node.parent) != null) { 155 if (isBanlanced(node)) { 156 // 更新高度 157 updateHeight(node); 158 } else { 159 // 恢复平衡 160 rebalance(node); 161 } 162 } 163 } 164 165 //重写这个创造节点,以下两个语句是AVL树独有的节点,但是又不影响BinaryTree和Bst,在BinaryTree中定义了 166 //creatnode这个方法,在BST中的add中也改了creatnode这个方法 167 @Override 168 protected Node<E> createNode(E element, Node<E> parent) { 169 return new AVLnode<>(element, parent); 170 } 171 //这个不能写在父类Node中,因为普通的二叉树不一定需要height这个属性,对其他二叉树来说这是不必要的浪费 172 private static class AVLnode<E> extends Node<E>{ 173 int height=1;//叶子节点高度为1 174 175 public AVLnode(E element, Node<E> parent) { 176 super(element, parent); 177 } 178 //计算平衡因子 179 public int balanceFactor(){ 180 int leftheight = left==null?0:((AVLnode<E>)left).height;//不强制转化的话,left是在BinaryTree中定义的节点,没有height这个属性 181 int rightheight = right==null?0:((AVLnode<E>)right).height; 182 return leftheight-rightheight; 183 } 184 //更新高度 185 public void updateheight(){ 186 int leftheight = left==null?0:((AVLnode<E>)left).height;//不强制转化的话,left是在BinaryTree中定义的节点,没有height这个属性 187 int rightheight = right==null?0:((AVLnode<E>)right).height; 188 height=1+Math.max(leftheight,rightheight);//左右子树最大高度,比如添加一个叶子节点,那么当前的高度就是1+1=2 189 } 190 //自己是否是左子树 191 public boolean isLeftChild(){ 192 return parent !=null &&this ==parent.left; 193 } 194 public boolean isRightChild(){ 195 return parent !=null &&this ==parent.right; 196 } 197 //找出自己高度比较高的子树,来进行进一步操作 198 public Node tallerChild(){ 199 int leftheight = left==null?0:((AVLnode<E>)left).height;//不强制转化的话,left是在BinaryTree中定义的节点,没有height这个属性 200 int rightheight = right==null?0:((AVLnode<E>)right).height; 201 if(leftheight>rightheight) return left; 202 if(leftheight<rightheight) return right; 203 return isLeftChild()?left:right; 204 } 205 } 206 private boolean isBanlanced(Node<E> node){ 207 return Math.abs (((AVLnode<E>)node).balanceFactor())<=1;//先把node强转,平衡因子小于等于1(绝对值) 208 } 209 /** 210 * 更新高度,封装到这个函数,看起来简洁,不然每次都要强制转化 211 */ 212 private void updateHeight(Node<E> node) { 213 ((AVLnode<E>) node).updateheight(); 214 } 215 }s
AVL树的思路:
1.在继承的BST中,要增加protected void afterAdd(Node<E> node){},这个方法要在AVLTREE中重写,这个afteradd的思路是,添加一个元素,如果平衡,那么更新高度,如果不平衡,那么就rabanlance(其中有两种思路)
然后在AVLTree中要增加一个节点,AVLAVLnode<E> extends Node<E>,因为这个节点不能写在父类Node中,因为普通的二叉树不一定需要AVLTree的这些属性和方法,对其他二叉树来说这是不必要的浪费
Node中有如下的方法 1.计算平衡因子 2.更新高度 3.自己是否是左子树4.找出自己高度比较高的子树,来进行进一步操作
rebance1(通法,找到相同规律,进行平衡操作)
rebance2(根据各种情况进行操作)
其他细节仔细阅读代码