定义:空树或者左子树和右子树高度差小于等于1且左右子树的子树也满足这个要求
在计算机科学中,AVL树是最早被发明的自平衡二叉查找树。在AVL树中,任一节点对应的两棵子树的最大高度差为1,因此它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下的时间复杂度都是。增加和删除元素的操作则可能需要借由一次或多次树旋转,以实现树的重新平衡。 维基百科
public class AVLTreeDemo {
public static void main(String[] args) {
int[] arr = {10, 12, 8, 9, 7, 6};
AVLTree avlTree = new AVLTree();
for (int i = 0; i < arr.length; i++) {
avlTree.add(new Node(arr[i]));
}
avlTree.infixOrder();
System.out.println(avlTree.getRoot().height());
System.out.println(avlTree.getRoot().leftHeight());
System.out.println(avlTree.getRoot().rightHeight());
System.out.println(avlTree.getRoot());
}
}
//创建AVL树
class AVLTree {
private Node root;
public Node getRoot() {
return root;
}
public Node search(int value) {
if (root == null) return null;
else return root.search(value);
}
public void add(Node node) {
if (root == null) root = node;
else root.add(node);
}
public void infixOrder() {
if (root == null) System.out.println("二叉排序树为空,不能遍历");
else root.infixOrder();
}
}
class Node {
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
//返回左子树高度
public int leftHeight() {
if (left == null) return 0;
return left.height();
}
//返回右子树高度
public int rightHeight() {
if (right == null) return 0;
return right.height();
}
//返回当前节点的高度(以该节点为根节点的树的高度)
public int height() {
return Math.max(left == null ? 0 : left.height(), right == null ? 0 : right.height()) + 1;
}
// 左旋转 右边高了,肯定有this.right
private void leftRotate() {
//创建新的节点,以当前根节点的值
Node newNode = new Node(value);
//把新的节点的左子树设置成当前节点左子树
newNode.left = left;
//把新的节点的右子树设置成右子树的左子树;
newNode.right = right.left;
//把当前节点的值替换成右子节点的值
value = right.value;
//把当前节点的右子树设置成右子树的右子树
right = right = right;
//把当前节点的左子树设置成新的节点
left = newNode;
}
//右旋转 左边高了
private void rightRotate() {
Node newNode = new Node(value);
newNode.right = right;
newNode.left = left.right;
value = left.value;
this.left = left.left;
this.right = newNode;
}
//查找要删除的节点
public Node search(int value) {
if (value == this.value) return this;
else if (value < this.value) {
if (this.left == null) return null;
return this.left.search(value);
} else {
if (this.right == null) return null;
return this.right.search(value);
}
}
// 递归的形式添加节点,注意需要满足二叉排序数的要求
public void add(Node node) {
if (node == null) return;
//判断传入的结点值,和当前子树的根节点的关系
if (node.value < this.value) {
if (this.left == null) this.left = node;
else {
this.left.add(node);
}
} else {
if (this.right == null) this.right = node;
else {
this.right.add(node);
}
}
//当添加完一个节点后 if(右子树的高度-左子树的高度>1 左旋)
if (rightHeight() - leftHeight() > 1) {
// 右子树的左子树高度大于右子树的右子节点树, 右旋,减小左边高度,增加右边高度
if (right != null && right.leftHeight() > right.rightHeight()) {
right.rightRotate();
}
leftRotate();
return; // 提高效率 这时候已经平衡
}
//左子树高度大于右子树高度 右旋
if (leftHeight() - rightHeight() > 1) {
//如果他的左子树的右节点高度大于其左节点高度
if (left != null && left.rightHeight() > left.leftHeight()) {
//先对当前节点的左节点 左旋转 减小右子树高度
left.leftRotate();
}
rightRotate();
}
}
public void infixOrder() {
if (left != null) left.infixOrder();
System.out.println(toString());
if (right != null) right.infixOrder();
}
@Override
public String toString() {
return "Node: " + value + ";";
}
}