AVL树是最先发明的自平衡二叉查找树。
特点:
- 任何节点的左右子树的高度相差的绝对值(平衡因子)<=1
- 空树的高度为0
- 本身首先是一棵二叉搜索树
- 查找、插入和删除在平均和最坏情况下都是O(logn)。
AVL树 JAVA 实现
1、节点定义
private static class AVLTreeNode<T extends Comparable<T>> {
private T element;
private AVLTreeNode<T> leftNode;
private AVLTreeNode<T> rightNode;
private int height;
public AVLTreeNode(T element, AVLTreeNode<T> leftNode, AVLTreeNode<T> rightNode) {
this.element = element;
this.leftNode = leftNode;
this.rightNode = rightNode;
this.height = Math.max(heightOfNode(leftNode), heightOfNode(rightNode)) + 1;
}
public AVLTreeNode(T element) {
this(element, null, null);
}
}
2、AVL树的定义
public class AVLTree<T extends Comparable<T>> {
private AVLTreeNode<T> rootNode; // 根节点
}
3、旋转
// 左左旋转
private AVLTreeNode<T> leftLeftRotation(AVLTreeNode<T> node) {
AVLTreeNode<T> node1;
node1 = node.leftNode;
node.leftNode = node1.rightNode;
node1.rightNode = node;
node1.height = Math.max(heightOfNode(node1.leftNode), heightOfNode(node1.rightNode)) + 1;
node.height = Math.max(heightOfNode(node.leftNode), heightOfNode(node.rightNode)) + 1;
return node1;
}
// 右右旋转
private AVLTreeNode<T> rightRightRotation(AVLTreeNode<T> node) {
AVLTreeNode<T> node1;
node1 = node.rightNode;
node.rightNode = node1.leftNode;
node1.leftNode = node;
node1.height = Math.max(heightOfNode(node1.leftNode), heightOfNode(node1.rightNode)) + 1;
node.height = Math.max(heightOfNode(node.leftNode), heightOfNode(node.rightNode)) + 1;
return node1;
}
// 右左旋转
private AVLTreeNode<T> rightLeftRotation(AVLTreeNode<T> node) {
node.rightNode = leftLeftRotation(node.rightNode);
return rightRightRotation(node);
}
//左右旋转
private AVLTreeNode<T> leftRightRotation(AVLTreeNode<T> node) {
node.leftNode = rightRightRotation(node.leftNode);
return leftLeftRotation(node);
}
4、计算节点高度
private static int heightOfNode(AVLTreeNode node) {
if (node == null) {
return 0;
}
return node.height;
}
5、获取AVL树的高度
public int height() {
return heightOfNode(this.rootNode);
}
6、修复节点
private AVLTreeNode<T> balance(AVLTreeNode<T> node) {
if (node == null) {
return null;
}
if ((heightOfNode(node.leftNode) - heightOfNode(node.rightNode)) > 1) {
if ((heightOfNode(node.leftNode.leftNode) - heightOfNode(node.leftNode.rightNode)) >= 1) {
// LL
leftLeftRotation(node);
} else {
// LR
rightLeftRotation(node);
}
} else if ((heightOfNode(node.rightNode) - heightOfNode(node.leftNode)) > 1) {
if ((heightOfNode(node.rightNode.rightNode) - heightOfNode(node.rightNode.leftNode)) >= 1) {
// RR
rightRightRotation(node);
} else {
// RL
leftRightRotation(node);
}
}
node.height = Math.max(heightOfNode(node.leftNode), heightOfNode(node.rightNode)) + 1;
return node;
}
7、插入一个节点
public void insert(T element) {
if (element == null) {
return;
}
rootNode = insert(element, rootNode);
}
// 给一个节点插入一个子节点
private AVLTreeNode<T> insert(T element, AVLTreeNode<T> node) {
if (node == null) {
node = new AVLTreeNode<T>(element);
}
int compareResult = element.compareTo(node.element);
if (compareResult < 0) {
node.leftNode = insert(element, node.leftNode);
} else if (compareResult > 0) {
node.rightNode = insert(element, node.rightNode);
}
node = balance(node);
return node;
}
8、获取树的最大值
public T findMaxElement() {
return findMaxNode(rootNode).element;
}
// 获取最大的节点
private AVLTreeNode<T> findMaxNode(AVLTreeNode<T> node) {
if(node == null) {
return null;
}
if (node.rightNode != null) {
return findMaxNode(node.rightNode);
} else {
return node;
}
}
9、获取树的最小值
public T findMinElement() {
return findMinNode(rootNode).element;
}
private AVLTreeNode<T> findMinNode(AVLTreeNode<T> node) {
if(node == null) {
return null;
}
if (node.leftNode != null) {
return findMinNode(node.leftNode);
} else {
return node;
}
}
10、根据节点的值删除一个节点
public void remove(T element) {
if (element == null) {
return;
}
rootNode = remove(element, rootNode);
}
private AVLTreeNode<T> remove(T element, AVLTreeNode<T> node) {
if (node == null) {
return node;
}
int compareResult = element.compareTo(node.element);
if (compareResult < 0) {
node.leftNode = remove(element, node.leftNode);
} else if (compareResult > 0) {
node.rightNode = remove(element, node.rightNode);
} else if (node.rightNode != null && node.leftNode != null) {
node.element = findMinNode(node.rightNode).element;
node.rightNode = remove(node.element, node.rightNode);
} else {
node = (node.rightNode == null) ? node.rightNode : node.leftNode;
}
return balance(node);
}