# AVL树
## 平衡二叉树 平衡二叉树特点:对于任意一个节点,左子树和右子树的高度差不能超过1 下图就是一棵平衡二叉树:
- 标注节点的高度:(叶子节点的高度为1)
- 计算平衡因子:(这里是根据左子树高度减去右子树高度进行计算):
## 计算节点的高度和平衡因子 ```java public class AVLTree,V>{ private class Node{ public K key; public V value; public Node left,right; public int height; public Node(K key,V value){ this.key=key; this.value=value; this.left=null; this.right=null; //叶子节点的高度是1 height=1; } } private Node root; private int size; public void add(K key, V value) { root=add(root,key,value); } //计算节点的高度 private int getNodeHeight(Node node){ if(node==null){ return 0; } return node.height; } //获取节点的平衡因子,左子树高度-右子树高度 private int getBalancedFactor(Node node){ if(node==null){ return 0; } return getNodeHeight(node.left)-getNodeHeight(node.right); } private Node add(Node node,K key,V value){ if(node==null){ size++; return new Node(key,value); } if(key.compareTo(node.key)<0){ node.left=add(node.left,key,value); }else if(key.compareTo(node.key)>0){ node.right=add(node.right,key,value); }else{ node.value=value; } //更新height node.height=1+Math.max(getNodeHeight(node.left),getNodeHeight(node.right)); //计算平衡因子 int balancedFactor=getBalancedFactor(node); if(Math.abs(balancedFactor)>1){ System.out.println("unblance:"+balancedFactor); } return node; } } ``` ## 检查二分搜索树和平衡树 - 利用BST中序遍历性质,判断是否是BST ```java //检查该树是否是平衡二叉树 public boolean isBST(){ List keys=new ArrayList<>(); inOrder(root,keys); for(int i=1;i0){ return false; } } return true; } private void inOrder(Node node, List keys){ if(node==null){ return; } inOrder(node.left,keys); keys.add(node.key); inOrder(node.right,keys); } ``` - 判断该树是否是平衡树 ```java //判断该二叉树是否是一棵平衡二叉树 public boolean isBalancedTree(){ return isBalancedTree(root); } private boolean isBalancedTree(Node node){ if(node==null){ return true; } int balancedFactor=getBalancedFactor(node); if(Math.abs(balancedFactor)>1){ return false; } return isBalancedTree(node.left) && isBalancedTree(node.right); } ``` ## AVL树的左旋转和右旋转 - AVL树的右旋转:插入的元素在不平衡的节点的左侧的左侧
- 右旋转针对的情况:以x、z为根节点的子树是平衡的BST树,添加一个元素以y为根节点的子树就不是平衡二叉树了
- 右旋转操作I:**x.right=y**
- 右旋转操作II:**y.left=T3**
- 右旋转之后,就是平衡的BST:假设z节点的高度是(h+1),可以验证以x为根节点的BST树是平衡树
- 代码实现: ```java // 对节点y进行向右旋转操作,返回旋转后新的根节点x // y x // / \ / \ // x T4 向右旋转 (y) z y // / \ - - - - - - - -> / \ / \ // z T3 T1 T2 T3 T4 // / \ // T1 T2 private Node rightRotate(Node y){ Node x=y.left; Node T3=x.right; //向右旋转 x.right=y; y.left=T3; //维护树的高度 y.height=1 + Math.max(getNodeHeight(y.left),getNodeHeight(y.right)); x.height=1 + Math.max(getNodeHeight(x.left),getNodeHeight(x.right)); return x; } private Node add(Node node,K key,V value){ if(node==null){ size++; return new Node(key,value); } if(key.compareTo(node.key)<0){ node.left=add(node.left,key,value); }else if(key.compareTo(node.key)>0){ node.right=add(node.right,key,value); }else{ node.value=value; } //更新height node.height=1+Math.max(getNodeHeight(node.left),getNodeHeight(node.right)); //计算平衡因子 int balancedFactor=getBalancedFactor(node); if(Math.abs(balancedFactor)>1){ System.out.println("unblance:"+balancedFactor); } //平衡维护-->右旋转 if(balancedFactor>1 && getBalancedFactor(node.left)>=0){ return rightRotate(node); } return node; } ``` - AVL的左旋转 ```java // 对节点y进行向左旋转操作,返回旋转后新的根节点x // y x // / \ / \ // T1 x 向左旋转 (y) y z // / \ - - - - - - - -> / \ / \ // T2 z T1 T2 T3 T4 // / \ // T3 T4 private Node leftRotate(Node y){ Node x=y.right; Node T2=x.left; //向左旋转 x.left=y; y.right=T2; //维护高度 y.height=1+Math.max(getNodeHeight(y.left),getNodeHeight(y.right)); x.height=1+Math.max(getNodeHeight(x.left),getNodeHeight(x.right)); return x; } private Node add(Node node,K key,V value){ if(node==null){ size++; return new Node(key,value); } if(key.compareTo(node.key)<0){ node.left=add(node.left,key,value); }else if(key.compareTo(node.key)>0){ node.right=add(node.right,key,value); }else{ node.value=value; } //更新height node.height=1+Math.max(getNodeHeight(node.left),getNodeHeight(node.right)); //计算平衡因子 int balancedFactor=getBalancedFactor(node); if(Math.abs(balancedFactor)>1){ System.out.println("unblance:"+balancedFactor); } //平衡维护-->右旋转 if(balancedFactor>1 && getBalancedFactor(node.left)>=0){ return rightRotate(node); } if(balancedFactor<-1 && getBalancedFactor(node.right)<=0){ return leftRotate(node); } return node; } ``` ## LR和RL - LR
- RL
```java //计算平衡因子 int balancedFactor=getBalancedFactor(node); /*if(Math.abs(balancedFactor)>1){ System.out.println("unblance:"+balancedFactor); }*/ //平衡维护 //LL if(balancedFactor>1 && getBalancedFactor(node.left)>=0){ return rightRotate(node); } //RR if(balancedFactor<-1 && getBalancedFactor(node.right)<=0){ return leftRotate(node); } //LR if(balancedFactor>1 && getBalancedFactor(node.left)<0){ Node x=node.left; node.left=leftRotate(x); //LL return rightRotate(node); } //RL if(balancedFactor<-1 && getBalancedFactor(node.right)>0){ Node x=node.right; node.right=rightRotate(x); //RR return leftRotate(node); } ``` ## 删除元素 ```java //从AVL中删除值为key的元素 public V remove(K key) { Node node=getNode(root,key); if(node!=null){ root=del(root,key); size--; } return null; } //获取Map中的最小的key private Node min(Node node){ if(node.left==null){ return node; } return min(node.left); } //删除以node为根结点的Map中的key最小的元素 private Node delMin(Node node){ if(node.left==null){ Node nodeRight=node.right; node.right=null; size--; return nodeRight; } node.left=delMin(node.left); //更新height node.height=1+Math.max(getNodeHeight(node.left),getNodeHeight(node.right)); //维护平衡 return keepBalance(node); } ////删除以node为根结点的Map中的键值为key的元素 private Node del(Node node, K key){ if(node==null){ return null; } //记录删除元素后,该BST的新的根节点 Node retNode=null; if(key.compareTo(node.key)<0){ node.left=del(node.left,key); retNode=node; }else if(key.compareTo(node.key)>0){ node.right=del(node.right,key); retNode=node; }else{ //节点node就是要删除的节点 //该节点只右有子树 if(node.left==null){ Node rightNode=node.right; node.right=null; size--; retNode=rightNode; }else if(node.right==null){ //该节点只有左子树 Node leftNode=node.left; node.left=null; size--; retNode=leftNode; }else{ //删除既有左子树又有右子树的节点 Node s=min(node.right); s.right=delMin(node.right); s.left=node.left; //删除node node.left=node.right=null; retNode=s; } } if(retNode==null){ return retNode; } //更新height retNode.height=1+Math.max(getNodeHeight(retNode.left),getNodeHeight(retNode.right)); //保持平衡 return keepBalance(retNode); } //维护以node为根节点的二叉树是平衡二叉树 private Node keepBalance(Node node){ //计算平衡因子 int balancedFactor=getBalancedFactor(node); //平衡维护 //LL if(balancedFactor>1 && getBalancedFactor(node.left)>=0){ return rightRotate(node); } //RR if(balancedFactor<-1 && getBalancedFactor(node.right)<=0){ return leftRotate(node); } //LR if(balancedFactor>1 && getBalancedFactor(node.left)<0){ Node x=node.left; node.left=leftRotate(x); //LL return rightRotate(node); } //RL if(balancedFactor<-1 && getBalancedFactor(node.right)>0){ Node x=node.right; node.right=rightRotate(x); //RR return leftRotate(node); } return node; } ``` ## 基于AVL树的集合和映射 - AVLMap ```java public class AVLMap,V> implements Map { private AVLTree avlTree; public AVLMap(){ avlTree=new AVLTree<>(); } @Override public void add(K key, V value) { avlTree.add(key,value); } @Override public V remove(K key) { return avlTree.remove(key); } @Override public boolean contains(K key) { return avlTree.contains(key); } @Override public V get(K key) { return avlTree.get(key); } @Override public void set(K key, V newValue) { avlTree.set(key,newValue); } @Override public int getSize() { return avlTree.getSize(); } @Override public boolean isEmpty() { return avlTree.isEmpty(); } } ``` - AVLSet ```java public class AVLSet> implements Set{ private AVLTree avlTree; public AVLSet(){ avlTree=new AVLTree<>(); } @Override public void add(K k) { avlTree.add(k,null); } @Override public void remove(K k) { avlTree.remove(k); } @Override public boolean contains(K k) { return avlTree.contains(k); } @Override public int getSize() { return avlTree.getSize(); } @Override public boolean isEmpty() { return avlTree.isEmpty(); } } ```