AVL树
在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。
AVL树特点
1.本身首先是一棵二叉搜索树。
2.带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1。
也就是说,AVL树,本质上是带了平衡功能的二叉查找树(二叉排序树,二叉搜索树)。
左旋转
avl树在左边子节点深度-右边子节点深度>1时,发生旋转
右旋转
avl树在右边子节点深度-左边子节点深度>1时,发生旋转
java代码实现
public class AVLTree<E extends Comparable> {
private Node root;
private int size;
public AVLTree() {
this.root = null;
this.size = 0;
}
public Node getRoot(){
return this.root;
}
public static void main(String[] args) {
AVLTree<Integer> avlTree = new AVLTree<>();
for (int i = 0; i < 100; i++) {
avlTree.add(i);
if(i % 10 == 4){
avlTree.remove(i);
}
}
System.out.println(avlTree.contains(20));
}
/**
* 返回树种元素的个数
*
* @return
*/
public int getSize() {
return this.size;
}
/**
* 判断树是否为空
*
* @return
*/
public boolean isEmpty() {
return this.size == 0;
}
private int getHeight(Node node) {
if (node == null) return 0;
return node.height;
}
private int getBalanceFactor(Node node) {
if (node == null) return 0;
return getHeight(node.left) - getHeight(node.right);
}
/**
* 判断树是否平衡
*
* @return
*/
public boolean isBalanced() {
return _isBalanced(root);
}
private boolean _isBalanced(Node node) {
if (node == null) {
return true;
}
int balanceFactor = getBalanceFactor(node);
if (balanceFactor > 1) {
return false;
}
return _isBalanced(node.left) && _isBalanced(node.right);
}
private boolean isBST() {
List<E> es = new ArrayList<>();
_inOrder(root, es);
for (int i = 1; i < es.size(); i++) {
if (es.get(i - 1).compareTo(es.get(i)) > 0) {
return false;
}
}
return true;
}
private void _inOrder(Node node, List<E> es) {
if (node == null) return;
_inOrder(node.left, es);
es.add(node.e);
_inOrder(node.right, es);
}
/**
* 右旋转
* 对节点y进行向右旋转操作,返回旋转后新的根节点x
* y x
* / \ / \
* x T4 向右旋转 (y) z y
* / \ - - - - - - - -> / \ / \
* z T3 T1 T2 T3 T4
* / \
* T1 T2
* @param y
* @return
*/
private Node rightRotate(Node y) {
Node x = y.left;
Node T3 = x.right;
x.right = y;
y.left = T3;
y.height = Math.max(getHeight(y.left), getHeight(y.right)) + 1;
x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;
return x;
}
/**
* 左旋转
* 对节点y进行向左旋转操作,返回旋转后新的根节点x
* y x
* / \ / \
* T1 x 向左旋转 (y) y z
* / \ - - - - - - - -> / \ / \
* T2 z T1 T2 T3 T4
* / \
* T3 T4
* @param y
* @return
*/
private Node leftRotate(Node y) {
Node x = y.right;
Node T2 = x.left;
x.left = y;
y.right = T2;
y.height = Math.max(getHeight(y.left), getHeight(y.right)) + 1;
x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;
return x;
}
/**
* 向树中添加元素
*
* @param e
*/
public void add(E e) {
root = _add(root, e);
}
private Node _add(Node node, E e) {
if (node == null) {
this.size++;
return new Node(e);
}
if (node.e.compareTo(e) < 0) {
node.right = _add(node.right, e);
} else if (node.e.compareTo(e) > 0) {
node.left = _add(node.left, e);
}
node.height = 1 + Math.max(getHeight(node.left), getHeight(node.right));
int factor = getBalanceFactor(node);
if (factor > 1 && getBalanceFactor(node.left) >= 0) {
return rightRotate(node);
}
if (factor < -1 && getBalanceFactor(node.right) <= 0) {
return leftRotate(node);
}
if (factor > 1 && getBalanceFactor(node.left) < 0) {
node.left = leftRotate(node.left);
return rightRotate(node);
}
if (factor < -1 && getBalanceFactor(node.right) > 0) {
node.right = rightRotate(node.right);
return leftRotate(node);
}
return node;
}
private Node _getNode(Node node, E e) {
if (node == null) return null;
if (node.e.compareTo(e) == 0) {
return node;
} else if (node.e.compareTo(e) > 0) {
return _getNode(node.left, e);
} else {
return _getNode(node.right, e);
}
}
/**
* 是否包含元素
*
* @param e
* @return
*/
public boolean contains(E e) {
return _getNode(root, e) != null;
}
/**
* 获取最小的节点
*
* @param node
* @return
*/
private Node _min(Node node) {
if (node.left == null) {
return node;
}
return _min(node.left);
}
/**
* 获取最大的节点
*
* @param node
* @return
*/
private Node _max(Node node) {
if (node.right == null) {
return node;
}
return _max(node.right);
}
private Node _removeMin(Node node) {
if (node.left == null) {
Node rightNode = node.right;
node.right = null;
this.size--;
return rightNode;
}
node.left = _removeMin(node.left);
return node;
}
public E remove(E e) {
Node node = _getNode(root, e);
if (node == null) return null;
root = _remove(root, e);
return e;
}
private Node _remove(Node node, E e) {
if (node == null) return null;
if (node.e.compareTo(e) > 0) {
node.left = _remove(node.left, e);
} else if (node.e.compareTo(e) < 0) {
node.right = _remove(node.right, e);
} else {
if (node.left == null) {
Node rightNode = node.right;
node.right = null;
this.size--;
node = rightNode;
}else if (node.right == null) {
Node leftNode = node.left;
node.left = null;
this.size--;
node = leftNode;
}else {
Node minRightNode = _min(node);
minRightNode = _removeMin(node.right);
minRightNode.left = node.left;
node.left = node.right = null;
node = minRightNode;
}
}
if(node == null){
return null;
}
node.height = Math.max(getHeight(node.left), getHeight(node.right) + 1);
int factor = getBalanceFactor(node);
if (factor > 1 && getBalanceFactor(node.left) >= 0) {
return rightRotate(node);
}
if (factor < -1 && getBalanceFactor(node.right) <= 0) {
return leftRotate(node);
}
if (factor > 1 && getBalanceFactor(node.left) < 0) {
node.left = leftRotate(node.left);
return rightRotate(node);
}
if (factor < -1 && getBalanceFactor(node.right) > 0) {
node.right = rightRotate(node.right);
return leftRotate(node);
}
return node;
}
class Node{
public E e;
public Node left, right;
public int height;
public Node(E e) {
this.e = e;
this.left = null;
this.right = null;
this.height = 1;
}
@Override
public String toString() {
return ""+e;
}
}
}