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(根据各种情况进行操作)

其他细节仔细阅读代码

 

 

 

 

 

 

 

 

 

 

 

 

 

 posted on 2021-09-25 19:06  “樂·~  阅读(42)  评论(0编辑  收藏  举报