平衡二叉树
平衡二叉树特点:对于任意一个节点,左子树和右子树的高度差不能超过1
下图就是一棵平衡二叉树:

- 标注节点的高度:(叶子节点的高度为1)

- 计算平衡因子:(这里是根据左子树高度减去右子树高度进行计算):

计算节点的高度和平衡因子
public class AVLTree<K extends Comparable<K>,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;//叶子节点的高度是1height=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;}//更新heightnode.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
//检查该树是否是平衡二叉树public boolean isBST(){List<K> keys=new ArrayList<>();inOrder(root,keys);for(int i=1;i<keys.size();i++){if(keys.get(i-1).compareTo(keys.get(i))>0){return false;}}return true;}private void inOrder(Node node, List<K> keys){if(node==null){return;}inOrder(node.left,keys);keys.add(node.key);inOrder(node.right,keys);}
- 判断该树是否是平衡树
//判断该二叉树是否是一棵平衡二叉树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树是平衡树

- 代码实现:
// 对节点y进行向右旋转操作,返回旋转后新的根节点x// y x// / \ / \// x T4 向右旋转 (y) z y// / \ - - - - - - - -> / \ / \// z T3 T1 T2 T3 T4// / \// T1 T2private 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;}//更新heightnode.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的左旋转
// 对节点y进行向左旋转操作,返回旋转后新的根节点x// y x// / \ / \// T1 x 向左旋转 (y) y z// / \ - - - - - - - -> / \ / \// T2 z T1 T2 T3 T4// / \// T3 T4private 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;}//更新heightnode.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


//计算平衡因子int balancedFactor=getBalancedFactor(node);/*if(Math.abs(balancedFactor)>1){System.out.println("unblance:"+balancedFactor);}*///平衡维护//LLif(balancedFactor>1 && getBalancedFactor(node.left)>=0){return rightRotate(node);}//RRif(balancedFactor<-1 && getBalancedFactor(node.right)<=0){return leftRotate(node);}//LRif(balancedFactor>1 && getBalancedFactor(node.left)<0){Node x=node.left;node.left=leftRotate(x);//LLreturn rightRotate(node);}//RLif(balancedFactor<-1 && getBalancedFactor(node.right)>0){Node x=node.right;node.right=rightRotate(x);//RRreturn leftRotate(node);}
删除元素
//从AVL中删除值为key的元素public V remove(K key) {Node node=getNode(root,key);if(node!=null){root=del(root,key);size--;}return null;}//获取Map中的最小的keyprivate 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);//更新heightnode.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;//删除nodenode.left=node.right=null;retNode=s;}}if(retNode==null){return retNode;}//更新heightretNode.height=1+Math.max(getNodeHeight(retNode.left),getNodeHeight(retNode.right));//保持平衡return keepBalance(retNode);}//维护以node为根节点的二叉树是平衡二叉树private Node keepBalance(Node node){//计算平衡因子int balancedFactor=getBalancedFactor(node);//平衡维护//LLif(balancedFactor>1 && getBalancedFactor(node.left)>=0){return rightRotate(node);}//RRif(balancedFactor<-1 && getBalancedFactor(node.right)<=0){return leftRotate(node);}//LRif(balancedFactor>1 && getBalancedFactor(node.left)<0){Node x=node.left;node.left=leftRotate(x);//LLreturn rightRotate(node);}//RLif(balancedFactor<-1 && getBalancedFactor(node.right)>0){Node x=node.right;node.right=rightRotate(x);//RRreturn leftRotate(node);}return node;}
基于AVL树的集合和映射
- AVL Map
public class AVLMap<K extends Comparable<K>,V> implements Map<K,V> {private AVLTree<K,V> avlTree;public AVLMap(){avlTree=new AVLTree<>();}@Overridepublic void add(K key, V value) {avlTree.add(key,value);}@Overridepublic V remove(K key) {return avlTree.remove(key);}@Overridepublic boolean contains(K key) {return avlTree.contains(key);}@Overridepublic V get(K key) {return avlTree.get(key);}@Overridepublic void set(K key, V newValue) {avlTree.set(key,newValue);}@Overridepublic int getSize() {return avlTree.getSize();}@Overridepublic boolean isEmpty() {return avlTree.isEmpty();}}
- AVL Set
