import java.util.Objects;
/**
* 平衡二叉树
*/
public class AVLTreeDemo {
public static void main(String[] args) {
int[] arr = { 10, 8, 9, 7, 6,15,2,25,12,55};
AVLTree avlTree = new AVLTree();
for (int i : arr) {
Node node = new Node(i);
avlTree.add(node);
}
System.out.println(avlTree.root.leftHeight());
System.out.println(avlTree.root.rightHeight());
}
}
class AVLTree {
Node root;
// 中序遍历
public void infixOrder() {
if (Objects.isNull(this.root)) {
System.out.println("this tree is null!");
return;
}
this.root.infixOrder();
}
// 添加节点
public void add(Node node) {
if (Objects.isNull(this.root)) {
this.root = node;
return;
}
this.root.add(node);
}
}
class Node {
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
/**
* 添加节点,需要满足排序二叉树
*
* @param node
*/
public void add(Node node) {
if (Objects.isNull(node)) {
return;
}
// 用传入节点的值和当前节点的值进行比较
if (node.value < this.value) {
if (Objects.isNull(this.left)) {
this.left = node;
} else {
this.left.add(node);
}
} else {
if (Objects.isNull(this.right)) {
this.right = node;
} else {
this.right.add(node);
}
}
// 右子树比左子树的高度大,需要左旋转
if ((rightHeight() - leftHeight()) > 1) {
if (Objects.nonNull(this.right) && this.right.leftHeight() > this.right.rightHeight()) {
// 右子树不为空,且右子树的左子树的高度大于右子树的右子树的高度,需要先让右子树进行右旋转
this.right.rightRotate();// 将右子树右旋转
}
leftRotate();
return;
}
// 左子树比右子树的高度大,需要右旋转
if ((leftHeight() - rightHeight()) > 1) {
if (Objects.nonNull(this.left) && this.left.rightHeight() > this.left.leftHeight()) {
// 左子树不为空,且左子树的右子树的高度大于左子树的左子树的高度,需要先让左子树进行左旋转
this.left.leftRotate();// 将左子树左旋转
}
rightRotate();
}
}
/**
* 右旋转,增加右子树的高度
*/
public void rightRotate() {
// 创建新的节点,值为当前节点的值
Node newNode = new Node(this.value);
// 设置新节点的右子节点为当前节点的右子树
newNode.right = this.right;
// 设置新节点的左子节点为当前节点的左子节点的右子树
newNode.left = this.left.right;
// 设置当前节点的值为当前节点的左子节点的值
this.value = this.left.value;
// 设置当前节点的左子节点为当前节点的左子节点的左子树
this.left = this.left.left;
// 设置当前节点的右子节点为新创建的节点
this.right = newNode;
}
/**
* 左旋转,增加左子树的高度
*/
public void leftRotate() {
// 创建新节点,值为当前节点的值
Node newNode = new Node(this.value);
// 设置新节点的左子树为当前节点的左子树
newNode.left = this.left;
// 设置新节点的右子树为当前节点的右子节点的左子树
newNode.right = this.right.left;
// 设置当前节点的值为当前节点的右子节点的值
this.value = this.right.value;
// 设置当前节点的右子节点为当前节点的右子节点的右子树
this.right = this.right.right;
// 设置当前节点的左子节点为新创建的节点
this.left = newNode;
}
/**
* 中序遍历二叉树
*/
public void infixOrder() {
if (Objects.nonNull(this.left)) {
this.left.infixOrder();
}
System.out.println(this);
if (Objects.nonNull(this.right)) {
this.right.infixOrder();
}
}
/**
* 获取左子树的高度
*
* @return
*/
public int leftHeight() {
if (Objects.isNull(left)) {
return 0;
}
return left.height();
}
/**
* 获取右子树的高度
*
* @return
*/
public int rightHeight() {
if (Objects.isNull(right)) {
return 0;
}
return right.height();
}
/**
* 得到树的高度
*
* @return
*/
public int height() {
return Math.max(Objects.isNull(left) ? 0 : left.height(), Objects.isNull(right) ? 0 : right.height()) + 1;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
}
左旋转过程图:
可以看到左旋转是增加了左子树的高度.右旋转反之,这样通过调整以达到左右子树的高度平衡.